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 private Map<String,List<String>> mapInt2Drv;
53 // Data structure to store our types (primitives and non-primitives) for compilation
54 private Map<String,String> mapPrimitives;
55 private Map<String,String> mapNonPrimitivesJava;
56 private Map<String,String> mapNonPrimitivesCplus;
57 // Other data structures
58 private Map<String,Integer> mapIntfaceObjId; // Maps interface name to object Id
59 private Map<String,Integer> mapNewIntfaceObjId; // Maps new interface name to its object Id (keep track of stubs)
60 private PrintWriter pw;
62 private String subdir;
63 private Map<String,Integer> mapPortCount; // Counter for ports
64 private static int portCount = 0;
65 private static int countObjId = 1; // Always increment object Id for a new stub/skeleton
66 private String mainClass;
67 private String controllerClass;
73 private final static String OUTPUT_DIRECTORY = "output_files";
74 private final static String INTERFACES_DIRECTORY = "interfaces";
75 private final static String VIRTUALS_DIRECTORY = "virtuals";
76 private final static String CODE_PREFIX = "iotcode";
77 private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
80 private enum ParamCategory {
82 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
83 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
85 STRUCT, // Struct type
86 USERDEFINED // Assumed as driver classes
93 public IoTCompiler() {
95 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
96 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
97 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
98 mapInt2NewIntName = new HashMap<String,String>();
99 mapInt2Drv = new HashMap<String,List<String>>();
100 mapIntfaceObjId = new HashMap<String,Integer>();
101 mapNewIntfaceObjId = new HashMap<String,Integer>();
102 mapPrimitives = new HashMap<String,String>();
103 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
104 mapNonPrimitivesJava = new HashMap<String,String>();
105 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
106 mapNonPrimitivesCplus = new HashMap<String,String>();
107 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
108 mapPortCount = new HashMap<String,Integer>();
110 dir = OUTPUT_DIRECTORY;
113 controllerClass = null;
118 * setDriverClass() sets the name of the driver class.
120 public void setDriverClass(String intface, String driverClass) {
122 List<String> drvList = mapInt2Drv.get(intface);
124 drvList = new ArrayList<String>();
125 drvList.add(driverClass);
126 mapInt2Drv.put(intface, drvList);
131 * setControllerClass() sets the name of the controller class.
133 public void setControllerClass(String _controllerClass) {
135 controllerClass = _controllerClass;
140 * setDataStructures() sets parse tree and other data structures based on policy files.
142 * It also generates parse tree (ParseTreeHandler) and
143 * copies useful information from parse tree into
144 * InterfaceDecl, CapabilityDecl, and RequiresDecl
146 * Additionally, the data structure handles are
147 * returned from tree-parsing for further process.
149 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
151 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
152 DeclarationHandler decHandler = new DeclarationHandler();
153 // Process ParseNode and generate Declaration objects
155 ptHandler.processInterfaceDecl();
156 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
157 decHandler.addInterfaceDecl(origInt, intDecl);
159 ptHandler.processCapabilityDecl();
160 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
161 decHandler.addCapabilityDecl(origInt, capDecl);
163 ptHandler.processRequiresDecl();
164 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
165 decHandler.addRequiresDecl(origInt, reqDecl);
167 ptHandler.processEnumDecl();
168 EnumDecl enumDecl = ptHandler.getEnumDecl();
169 decHandler.addEnumDecl(origInt, enumDecl);
171 ptHandler.processStructDecl();
172 StructDecl structDecl = ptHandler.getStructDecl();
173 decHandler.addStructDecl(origInt, structDecl);
175 mapIntfacePTH.put(origInt, ptHandler);
176 mapIntDeclHand.put(origInt, decHandler);
177 // Set object Id counter to 0 for each interface
178 mapIntfaceObjId.put(origInt, countObjId++);
183 * getMethodsForIntface() reads for methods in the data structure
185 * It is going to give list of methods for a certain interface
186 * based on the declaration of capabilities.
188 public void getMethodsForIntface(String origInt) {
190 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
191 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
192 // Get set of new interfaces, e.g. CameraWithCaptureAndData
193 // Generate this new interface with all the methods it needs
194 // from different capabilities it declares
195 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
196 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
197 Set<String> setIntfaces = reqDecl.getInterfaces();
198 for (String strInt : setIntfaces) {
200 // Initialize a set of methods
201 Set<String> setMethods = new HashSet<String>();
202 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
203 List<String> listCapab = reqDecl.getCapabList(strInt);
204 for (String strCap : listCapab) {
206 // Get list of methods for each capability
207 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
208 List<String> listCapabMeth = capDecl.getMethods(strCap);
209 for (String strMeth : listCapabMeth) {
211 // Add methods into setMethods
212 // This is to also handle redundancies (say two capabilities
213 // share the same methods)
214 setMethods.add(strMeth);
217 // Add interface and methods information into map
218 mapNewIntMethods.put(strInt, setMethods);
219 // Map new interface method name to the original interface
220 // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
221 mapInt2NewIntName.put(origInt, strInt);
222 if (mainClass == null) // Take the first class as the main class (whichever is placed first in the order of compilation files)
225 // Map the map of interface-methods to the original interface
226 mapInt2NewInts.put(origInt, mapNewIntMethods);
235 * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
237 private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
239 for (String method : methods) {
241 List<String> methParams = intDecl.getMethodParams(method);
242 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
243 print("public " + intDecl.getMethodType(method) + " " +
244 intDecl.getMethodId(method) + "(");
245 for (int i = 0; i < methParams.size(); i++) {
246 // Check for params with driver class types and exchange it
247 // with its remote interface
248 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
249 print(paramType + " " + methParams.get(i));
250 // Check if this is the last element (don't print a comma)
251 if (i != methParams.size() - 1) {
261 * HELPER: writeMethodJavaInterface() writes the method of the interface
263 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
265 for (String method : methods) {
267 List<String> methParams = intDecl.getMethodParams(method);
268 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
269 print("public " + intDecl.getMethodType(method) + " " +
270 intDecl.getMethodId(method) + "(");
271 for (int i = 0; i < methParams.size(); i++) {
272 // Check for params with driver class types and exchange it
273 // with its remote interface
274 String paramType = methPrmTypes.get(i);
275 print(paramType + " " + methParams.get(i));
276 // Check if this is the last element (don't print a comma)
277 if (i != methParams.size() - 1) {
287 * HELPER: generateEnumJava() writes the enumeration declaration
289 private void generateEnumJava() throws IOException {
291 // Create a new directory
292 createDirectory(dir);
293 String path = createDirectories(dir, INTERFACES_DIRECTORY);
294 for (String intface : mapIntfacePTH.keySet()) {
295 // Get the right EnumDecl
296 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
297 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
298 Set<String> enumTypes = enumDecl.getEnumDeclarations();
299 // Iterate over enum declarations
300 for (String enType : enumTypes) {
301 // Open a new file to write into
302 FileWriter fw = new FileWriter(path + "/" + enType + ".java");
303 pw = new PrintWriter(new BufferedWriter(fw));
304 println("package " + INTERFACE_PACKAGE + ";\n");
305 println("public enum " + enType + " {");
306 List<String> enumMembers = enumDecl.getMembers(enType);
307 for (int i = 0; i < enumMembers.size(); i++) {
309 String member = enumMembers.get(i);
311 // Check if this is the last element (don't print a comma)
312 if (i != enumMembers.size() - 1)
319 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
326 * HELPER: generateStructJava() writes the struct declaration
328 private void generateStructJava() throws IOException {
330 // Create a new directory
331 createDirectory(dir);
332 String path = createDirectories(dir, INTERFACES_DIRECTORY);
333 for (String intface : mapIntfacePTH.keySet()) {
334 // Get the right StructDecl
335 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
336 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
337 List<String> structTypes = structDecl.getStructTypes();
338 // Iterate over enum declarations
339 for (String stType : structTypes) {
340 // Open a new file to write into
341 FileWriter fw = new FileWriter(path + "/" + stType + ".java");
342 pw = new PrintWriter(new BufferedWriter(fw));
343 println("package " + INTERFACE_PACKAGE + ";\n");
344 println("public class " + stType + " {");
345 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
346 List<String> structMembers = structDecl.getMembers(stType);
347 for (int i = 0; i < structMembers.size(); i++) {
349 String memberType = structMemberTypes.get(i);
350 String member = structMembers.get(i);
351 println("public static " + memberType + " " + member + ";");
355 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
362 * generateJavaLocalInterface() writes the local interface and provides type-checking.
364 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
365 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
366 * The local interface has to be the input parameter for the stub and the stub
367 * interface has to be the input parameter for the local class.
369 public void generateJavaLocalInterfaces() throws IOException {
371 // Create a new directory
372 createDirectory(dir);
373 String path = createDirectories(dir, INTERFACES_DIRECTORY);
374 for (String intface : mapIntfacePTH.keySet()) {
375 // Open a new file to write into
376 FileWriter fw = new FileWriter(path + "/" + intface + ".java");
377 pw = new PrintWriter(new BufferedWriter(fw));
378 // Pass in set of methods and get import classes
379 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
380 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
381 List<String> methods = intDecl.getMethods();
382 Set<String> importClasses = getImportClasses(methods, intDecl);
383 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
384 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
385 println("package " + INTERFACE_PACKAGE + ";\n");
386 printImportStatements(allImportClasses);
387 // Write interface header
389 println("public interface " + intface + " {");
391 writeMethodJavaLocalInterface(methods, intDecl);
394 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
400 * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
402 private void updateIntfaceObjIdMap(String intface, String newIntface) {
404 // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
405 Integer objId = mapIntfaceObjId.get(intface);
406 mapNewIntfaceObjId.put(newIntface, objId);
411 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
413 public void generateJavaInterfaces() throws IOException {
415 // Create a new directory
416 String path = createDirectories(dir, subdir);
417 path = createDirectories(dir + "/" + subdir, INTERFACES_DIRECTORY);
418 for (String intface : mapIntfacePTH.keySet()) {
420 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
421 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
423 // Open a new file to write into
424 String newIntface = intMeth.getKey();
425 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
426 pw = new PrintWriter(new BufferedWriter(fw));
427 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
428 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
429 // Pass in set of methods and get import classes
430 Set<String> methods = intMeth.getValue();
431 Set<String> importClasses = getImportClasses(methods, intDecl);
432 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
433 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
434 println("package " + INTERFACE_PACKAGE + ";\n");
435 printImportStatements(allImportClasses);
436 // Write interface header
438 println("public interface " + newIntface + " {\n");
439 updateIntfaceObjIdMap(intface, newIntface);
441 writeMethodJavaInterface(methods, intDecl);
444 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
451 * HELPER: writePropertiesJavaPermission() writes the permission in properties
453 private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
455 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
456 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
457 String newIntface = intMeth.getKey();
458 int newObjectId = getNewIntfaceObjectId(newIntface);
459 Set<String> methodIds = intMeth.getValue();
460 print("private static Integer[] object" + newObjectId + "Permission = { ");
462 for (String methodId : methodIds) {
463 int methodNumId = intDecl.getMethodNumId(methodId);
464 print(Integer.toString(methodNumId));
465 // Check if this is the last element (don't print a comma)
466 if (i != methodIds.size() - 1) {
472 println("private static List<Integer> set" + newObjectId + "Allowed;");
478 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
480 private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
483 Integer objId = mapIntfaceObjId.get(intface);
484 println("private int objectId = " + objId + ";");
485 println("private IoTRMIComm rmiComm;");
486 // Write the list of AtomicBoolean variables
487 println("// Synchronization variables");
488 for (String method : methods) {
489 // Generate AtomicBooleans for methods that have return values
490 String returnType = intDecl.getMethodType(method);
491 int methodNumId = intDecl.getMethodNumId(method);
492 if (!returnType.equals("void")) {
493 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
501 * HELPER: writeConstructorJavaPermission() writes the permission in constructor
503 private void writeConstructorJavaPermission(String intface) {
505 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
506 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
507 String newIntface = intMeth.getKey();
508 int newObjectId = getNewIntfaceObjectId(newIntface);
509 println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
515 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
517 private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
519 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
520 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
521 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
524 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
526 // Register the AtomicBoolean variables
527 for (String method : methods) {
528 // Generate AtomicBooleans for methods that have return values
529 String returnType = intDecl.getMethodType(method);
530 int methodNumId = intDecl.getMethodNumId(method);
531 if (!returnType.equals("void")) {
532 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
535 println("IoTRMIUtil.mapStub.put(objectId, this);");
541 * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
543 private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
545 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
546 println("rmiComm = _rmiComm;");
547 println("objectId = _objectId;");
548 // Register the AtomicBoolean variables
549 for (String method : methods) {
550 // Generate AtomicBooleans for methods that have return values
551 String returnType = intDecl.getMethodType(method);
552 int methodNumId = intDecl.getMethodNumId(method);
553 if (!returnType.equals("void")) {
554 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
562 * HELPER: getPortCount() gets port count for different stubs and skeletons
564 private int getPortCount(String intface) {
566 if (!mapPortCount.containsKey(intface))
567 mapPortCount.put(intface, portCount++);
568 return mapPortCount.get(intface);
573 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
575 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
577 // Iterate and find enum declarations
578 for (int i = 0; i < methParams.size(); i++) {
579 String paramType = methPrmTypes.get(i);
580 String param = methParams.get(i);
581 String simpleType = getGenericType(paramType);
582 if (isEnumClass(simpleType)) {
583 // Check if this is enum type
584 if (isArray(param)) { // An array
585 println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
586 println("int paramEnum" + i + "[] = new int[len" + i + "];");
587 println("for (int i = 0; i < len" + i + "; i++) {");
588 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
590 } else if (isList(paramType)) { // A list
591 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
592 println("int paramEnum" + i + "[] = new int[len" + i + "];");
593 println("for (int i = 0; i < len" + i + "; i++) {");
594 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
596 } else { // Just one element
597 println("int paramEnum" + i + "[] = new int[1];");
598 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
606 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
608 private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
610 // Write the wait-for-return-value part
611 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
612 // Strips off array "[]" for return type
613 String pureType = getSimpleArrayType(getGenericType(retType));
614 // Take the inner type of generic
615 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
616 pureType = getGenericType(retType);
617 if (isEnumClass(pureType)) {
618 // Check if this is enum type
620 println("int[] retEnum = (int[]) retObj;");
621 println(pureType + "[] enumVals = " + pureType + ".values();");
622 if (isArray(retType)) { // An array
623 println("int retLen = retEnum.length;");
624 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
625 println("for (int i = 0; i < retLen; i++) {");
626 println("enumRetVal[i] = enumVals[retEnum[i]];");
628 } else if (isList(retType)) { // A list
629 println("int retLen = retEnum.length;");
630 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
631 println("for (int i = 0; i < retLen; i++) {");
632 println("enumRetVal.add(enumVals[retEnum[i]]);");
634 } else { // Just one element
635 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
637 println("return enumRetVal;");
643 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
645 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
646 InterfaceDecl intDecl, String method) {
648 // Iterate and find struct declarations
649 for (int i = 0; i < methParams.size(); i++) {
650 String paramType = methPrmTypes.get(i);
651 String param = methParams.get(i);
652 String simpleType = getGenericType(paramType);
653 if (isStructClass(simpleType)) {
654 // Check if this is enum type
655 int methodNumId = intDecl.getMethodNumId(method);
656 String helperMethod = methodNumId + "struct" + i;
657 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
658 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
659 if (isArray(param)) { // An array
660 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
661 } else if (isList(paramType)) { // A list
662 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
663 } else { // Just one element
664 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
666 println("rmiComm.remoteCall(objectId, methodIdStruct" + i +
667 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
674 * HELPER: isStructPresent() checks presence of struct
676 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
678 // Iterate and find enum declarations
679 for (int i = 0; i < methParams.size(); i++) {
680 String paramType = methPrmTypes.get(i);
681 String param = methParams.get(i);
682 String simpleType = getGenericType(paramType);
683 if (isStructClass(simpleType))
691 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
693 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
695 // Iterate and find struct declarations - count number of params
696 for (int i = 0; i < methParams.size(); i++) {
697 String paramType = methPrmTypes.get(i);
698 String param = methParams.get(i);
699 String simpleType = getGenericType(paramType);
700 if (isStructClass(simpleType)) {
701 int members = getNumOfMembers(simpleType);
702 if (isArray(param)) { // An array
703 String structLen = getSimpleArrayType(param) + ".length";
704 print(members + "*" + structLen);
705 } else if (isList(paramType)) { // A list
706 String structLen = getSimpleArrayType(param) + ".size()";
707 print(members + "*" + structLen);
709 print(Integer.toString(members));
712 if (i != methParams.size() - 1) {
720 * HELPER: writeStructMembersJavaStub() writes parameters of struct
722 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
724 // Get the struct declaration for this struct and generate initialization code
725 StructDecl structDecl = getStructDecl(simpleType);
726 List<String> memTypes = structDecl.getMemberTypes(simpleType);
727 List<String> members = structDecl.getMembers(simpleType);
728 if (isArray(param)) { // An array
729 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
730 for (int i = 0; i < members.size(); i++) {
731 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
732 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
733 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
734 print(getSimpleIdentifier(members.get(i)));
738 } else if (isList(paramType)) { // A list
739 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
740 for (int i = 0; i < members.size(); i++) {
741 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
742 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
743 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
744 print(getSimpleIdentifier(members.get(i)));
748 } else { // Just one struct element
749 for (int i = 0; i < members.size(); i++) {
750 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
751 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
752 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
753 print(getSimpleIdentifier(members.get(i)));
761 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
763 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
765 print("int paramLen = ");
766 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
768 println("Object[] paramObj = new Object[paramLen];");
769 println("Class<?>[] paramCls = new Class<?>[paramLen];");
770 println("int pos = 0;");
771 // Iterate again over the parameters
772 for (int i = 0; i < methParams.size(); i++) {
773 String paramType = methPrmTypes.get(i);
774 String param = methParams.get(i);
775 String simpleType = getGenericType(paramType);
776 if (isStructClass(simpleType)) {
777 writeStructMembersJavaStub(simpleType, paramType, param);
778 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
779 println("paramCls[pos] = int[].class;");
780 println("paramObj[pos++] = objIdSent" + i + ";");
782 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
783 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
784 print("paramObj[pos++] = ");
785 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
794 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
796 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
798 // Get the struct declaration for this struct and generate initialization code
799 StructDecl structDecl = getStructDecl(simpleType);
800 List<String> memTypes = structDecl.getMemberTypes(simpleType);
801 List<String> members = structDecl.getMembers(simpleType);
802 if (isArrayOrList(retType, retType)) { // An array or list
803 println("for(int i = 0; i < retLen; i++) {");
805 if (isArray(retType)) { // An array
806 for (int i = 0; i < members.size(); i++) {
807 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
808 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
809 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
812 } else if (isList(retType)) { // A list
813 println(simpleType + " structRetMem = new " + simpleType + "();");
814 for (int i = 0; i < members.size(); i++) {
815 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
816 print("structRetMem." + getSimpleIdentifier(members.get(i)));
817 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
819 println("structRet.add(structRetMem);");
821 } else { // Just one struct element
822 for (int i = 0; i < members.size(); i++) {
823 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
824 print("structRet." + getSimpleIdentifier(members.get(i)));
825 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
828 println("return structRet;");
833 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
835 private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
837 // Handle the returned struct size
838 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
839 // Minimum retLen is 1 if this is a single struct object
840 println("int retLen = (int) retObj;");
841 int numMem = getNumOfMembers(simpleType);
842 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
843 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
844 println("int retPos = 0;");
845 // Get the struct declaration for this struct and generate initialization code
846 StructDecl structDecl = getStructDecl(simpleType);
847 List<String> memTypes = structDecl.getMemberTypes(simpleType);
848 List<String> members = structDecl.getMembers(simpleType);
849 if (isArrayOrList(retType, retType)) { // An array or list
850 println("for(int i = 0; i < retLen; i++) {");
851 for (int i = 0; i < members.size(); i++) {
852 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
853 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
854 println("retClsVal[retPos++] = null;");
857 } else { // Just one struct element
858 for (int i = 0; i < members.size(); i++) {
859 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
860 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
861 println("retClsVal[retPos++] = null;");
864 // Handle the actual returned struct
865 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
866 if (isArray(retType)) { // An array
867 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
868 println("for(int i = 0; i < retLen; i++) {");
869 println("structRet[i] = new " + simpleType + "();");
871 } else if (isList(retType)) { // A list
872 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
874 println(simpleType + " structRet = new " + simpleType + "();");
875 println("int retObjPos = 0;");
876 writeStructRetMembersJavaStub(simpleType, retType);
881 * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
883 private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
885 println("// Waiting for return value");
886 int methodNumId = intDecl.getMethodNumId(method);
887 println("while (!retValueReceived" + methodNumId + ".get());");
888 println(getReturnValue);
889 println("retValueReceived" + methodNumId + ".set(false);");
890 println("rmiComm.setGetReturnBytes();\n");
895 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
897 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
898 List<String> methPrmTypes, String method, Set<String> callbackType) {
900 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
901 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
902 String retType = intDecl.getMethodType(method);
903 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
904 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
905 // Generate array of parameter types
906 if (isStructPresent(methParams, methPrmTypes)) {
907 writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
909 print("Class<?>[] paramCls = new Class<?>[] { ");
910 for (int i = 0; i < methParams.size(); i++) {
911 String prmType = methPrmTypes.get(i);
912 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
913 print("int[].class");
914 } else { // Generate normal classes if it's not a callback object
915 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
916 print(getSimpleType(getEnumType(paramType)) + ".class");
918 // Check if this is the last element (don't print a comma)
919 if (i != methParams.size() - 1) {
924 // Generate array of parameter objects
925 print("Object[] paramObj = new Object[] { ");
926 for (int i = 0; i < methParams.size(); i++) {
927 String paramType = methPrmTypes.get(i);
928 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
929 print("objIdSent" + i);
931 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
932 // Check if this is the last element (don't print a comma)
933 if (i != methParams.size() - 1) {
939 // Send method call first and wait for return value separately
940 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
941 // Check if this is "void"
942 if (!retType.equals("void")) { // We do have a return value
943 // Generate array of parameter types
944 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
945 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
947 // This is an enum type
948 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
949 //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
950 checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
951 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
952 // Check if the return value NONPRIMITIVES
953 String retGenValType = getGenericType(retType);
954 println("Class<?> retGenValType = " + retGenValType + ".class;");
955 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
956 println("return (" + retType + ")retObj;");
958 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
959 println("return (" + retType + ")retObj;");
967 * HELPER: returnGenericCallbackType() returns the callback type
969 private String returnGenericCallbackType(String paramType) {
971 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
972 return getGenericType(paramType);
979 * HELPER: checkCallbackType() checks the callback type
981 private boolean checkCallbackType(String paramType, Set<String> callbackType) {
983 String prmType = returnGenericCallbackType(paramType);
984 if (callbackType == null) // If there is no callbackType it means not a callback method
987 for (String type : callbackType) {
988 if (type.equals(prmType))
989 return true; // Check callbackType one by one
997 * HELPER: checkCallbackType() checks the callback type
999 private boolean checkCallbackType(String paramType, String callbackType) {
1001 String prmType = returnGenericCallbackType(paramType);
1002 if (callbackType == null) // If there is no callbackType it means not a callback method
1005 return callbackType.equals(prmType);
1010 * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1012 private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1014 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1015 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1016 if (isMultipleCallbacks)
1017 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1019 println("objIdSent" + counter + "[0] = newObjIdSent;");
1020 println("rmiComm.decrementObjectIdCounter();");
1021 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1022 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1023 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1024 println("Thread thread = new Thread() {");
1025 println("public void run() {");
1027 println("skel" + counter + ".___waitRequestInvokeMethod();");
1028 println("} catch (Exception ex) {");
1029 println("ex.printStackTrace();");
1030 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " +
1031 callbackType + "_Skeleton!\");");
1035 println("thread.start();");
1036 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1040 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1041 if (isMultipleCallbacks)
1042 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1044 println("objIdSent" + counter + "[0] = newObjIdSent;");
1050 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1052 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1053 List<String> methPrmTypes, String method, Set<String> callbackType) {
1055 // Determine callback object counter type (List vs. single variable)
1056 for (int i = 0; i < methParams.size(); i++) {
1057 String paramType = methPrmTypes.get(i);
1058 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1059 print("int[] objIdSent" + i + " = ");
1060 String param = methParams.get(i);
1061 if (isArray(methParams.get(i)))
1062 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1063 else if (isList(methPrmTypes.get(i)))
1064 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1066 println("new int[1];");
1070 // Check if this is single object, array, or list of objects
1071 for (int i = 0; i < methParams.size(); i++) {
1072 String paramType = methPrmTypes.get(i);
1073 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1074 String param = methParams.get(i);
1075 if (isArrayOrList(paramType, param)) { // Generate loop
1076 println("int cnt" + i + " = 0;");
1077 println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1078 writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1080 writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1081 if (isArrayOrList(paramType, param))
1086 println(" catch (Exception ex) {");
1087 println("ex.printStackTrace();");
1088 println("throw new Error(\"Exception when generating skeleton objects!\");");
1094 * HELPER: writeMethodJavaStub() writes the methods of the stub class
1096 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1098 for (String method : methods) {
1100 List<String> methParams = intDecl.getMethodParams(method);
1101 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1102 print("public " + intDecl.getMethodType(method) + " " +
1103 intDecl.getMethodId(method) + "(");
1104 boolean isCallbackMethod = false;
1105 //String callbackType = null;
1106 Set<String> callbackType = new HashSet<String>();
1107 for (int i = 0; i < methParams.size(); i++) {
1109 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1110 // Check if this has callback object
1111 if (callbackClasses.contains(paramType)) {
1112 isCallbackMethod = true;
1113 //callbackType = paramType;
1114 callbackType.add(paramType);
1115 // Even if there're 2 callback arguments, we expect them to be of the same interface
1117 print(methPrmTypes.get(i) + " " + methParams.get(i));
1118 // Check if this is the last element (don't print a comma)
1119 if (i != methParams.size() - 1) {
1124 // Now, write the body of stub!
1125 if (isCallbackMethod)
1126 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1127 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1134 * HELPER: getStubInterface() gets stub interface name based on original interface
1136 public String getStubInterface(String intface) {
1138 return mapInt2NewIntName.get(intface);
1143 * generateJavaStubClasses() generate stubs based on the methods list in Java
1145 public void generateJavaStubClasses() throws IOException {
1147 // Create a new directory
1148 String path = createDirectories(dir, subdir);
1149 for (String intface : mapIntfacePTH.keySet()) {
1151 // Check if there is more than 1 class that uses the same interface
1152 List<String> drvList = mapInt2Drv.get(intface);
1153 for(int i = 0; i < drvList.size(); i++) {
1155 String driverClass = drvList.get(i);
1156 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1157 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1159 // Open a new file to write into
1160 String newIntface = intMeth.getKey();
1161 String newStubClass = newIntface + "_Stub";
1162 String packageClass = null;
1163 // Check if this interface is a callback class
1164 if(isCallbackClass(intface)) {
1165 packageClass = CODE_PREFIX + "." + driverClass;
1166 path = createDirectories(dir + "/" + subdir, driverClass);
1168 packageClass = controllerClass;
1169 path = createDirectories(dir + "/" + subdir, controllerClass);
1171 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1172 pw = new PrintWriter(new BufferedWriter(fw));
1173 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1174 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1175 // Pass in set of methods and get import classes
1176 Set<String> methods = intMeth.getValue();
1177 Set<String> importClasses = getImportClasses(methods, intDecl);
1178 List<String> stdImportClasses = getStandardJavaImportClasses();
1179 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1180 // Find out if there are callback objects
1181 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1182 boolean callbackExist = !callbackClasses.isEmpty();
1183 println("package " + packageClass + ";\n");
1184 printImportStatements(allImportClasses);
1185 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
1186 // Write class header
1187 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1189 writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1190 // Write constructor
1191 writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1192 // Write callback constructor (used if this stub is treated as a callback stub)
1193 writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1195 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1198 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1206 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1208 private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1210 println("private " + intface + " mainObj;");
1211 Integer objId = mapIntfaceObjId.get(intface);
1212 println("private int objectId = " + objId + ";");
1213 println("// Communications and synchronizations");
1214 println("private IoTRMIComm rmiComm;");
1215 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1216 println("private AtomicBoolean methodReceived;");
1217 println("private byte[] methodBytes = null;");
1218 println("// Permissions");
1219 writePropertiesJavaPermission(intface, intDecl);
1225 * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1227 private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1229 // Use this set to handle two same methodIds
1230 for (String method : methods) {
1231 List<String> methParams = intDecl.getMethodParams(method);
1232 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1233 // Check for params with structs
1234 for (int i = 0; i < methParams.size(); i++) {
1235 String paramType = methPrmTypes.get(i);
1236 String param = methParams.get(i);
1237 String simpleType = getGenericType(paramType);
1238 if (isStructClass(simpleType)) {
1239 int methodNumId = intDecl.getMethodNumId(method);
1240 String helperMethod = methodNumId + "struct" + i;
1241 int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1242 // Iterate over interfaces to give permissions to
1243 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1244 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1245 String newIntface = intMeth.getKey();
1246 int newObjectId = getNewIntfaceObjectId(newIntface);
1247 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1256 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1258 private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1259 Collection<String> methods, boolean callbackExist) {
1261 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1262 println("mainObj = _mainObj;");
1263 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1264 // Generate permission control initialization
1265 writeConstructorJavaPermission(intface);
1266 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1267 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1268 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1269 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1270 println("methodReceived = new AtomicBoolean(false);");
1271 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1272 println("Thread thread1 = new Thread() {");
1273 println("public void run() {");
1275 println("___waitRequestInvokeMethod();");
1277 println("catch (Exception ex)");
1279 println("ex.printStackTrace();");
1283 println("thread1.start();");
1289 * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1291 private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1292 Collection<String> methods, boolean callbackExist) {
1294 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1295 println("mainObj = _mainObj;");
1296 println("rmiComm = _rmiComm;");
1297 println("objectId = _objectId;");
1298 // Generate permission control initialization
1299 writeConstructorJavaPermission(intface);
1300 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1301 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1302 println("methodReceived = new AtomicBoolean(false);");
1303 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1309 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1311 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1313 if (methodType.equals("void"))
1314 print("mainObj." + methodId + "(");
1316 print("return mainObj." + methodId + "(");
1317 for (int i = 0; i < methParams.size(); i++) {
1319 print(getSimpleIdentifier(methParams.get(i)));
1320 // Check if this is the last element (don't print a comma)
1321 if (i != methParams.size() - 1) {
1330 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1332 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1334 for (String method : methods) {
1336 List<String> methParams = intDecl.getMethodParams(method);
1337 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1338 String methodId = intDecl.getMethodId(method);
1339 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1340 for (int i = 0; i < methParams.size(); i++) {
1342 String origParamType = methPrmTypes.get(i);
1343 String paramType = checkAndGetParamClass(origParamType);
1344 print(paramType + " " + methParams.get(i));
1345 // Check if this is the last element (don't print a comma)
1346 if (i != methParams.size() - 1) {
1351 // Now, write the body of skeleton!
1352 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1359 * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1361 private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1363 println(exchParamType + " newStub" + counter + " = null;");
1364 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1365 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1366 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1367 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1368 println("rmiComm.decrementObjectIdCounter();");
1371 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1377 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1379 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1380 Set<String> callbackType, boolean isStructMethod) {
1382 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1383 String offsetPfx = "";
1385 offsetPfx = "offset";
1386 // Iterate over callback objects
1387 for (int i = 0; i < methParams.size(); i++) {
1388 String paramType = methPrmTypes.get(i);
1389 String param = methParams.get(i);
1390 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1391 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1392 // Print array if this is array or list if this is a list of callback objects
1393 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1394 if (isArray(param)) {
1395 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1396 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1397 } else if (isList(paramType)) {
1398 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1399 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1401 println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1402 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1405 // Generate a loop if needed
1406 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1407 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1408 if (isArray(param)) {
1409 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1410 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1411 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1412 println("stub" + i + "[i] = newStub" + i + ";");
1414 } else if (isList(paramType)) {
1415 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1416 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1417 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1418 println("stub" + i + ".add(newStub" + i + ");");
1421 println(exchParamType + " stub" + i + " = newStub" + i + ";");
1422 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1425 return mapStubParam;
1430 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1432 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1434 String offsetPfx = "";
1436 offsetPfx = "offset";
1437 // Iterate and find enum declarations
1438 boolean printed = false;
1439 for (int i = 0; i < methParams.size(); i++) {
1440 String paramType = methPrmTypes.get(i);
1441 String param = methParams.get(i);
1442 String simpleType = getGenericType(paramType);
1443 if (isEnumClass(simpleType)) {
1444 // Check if this is enum type
1445 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1447 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1450 if (isArray(param)) { // An array
1451 println("int len" + i + " = paramInt" + i + ".length;");
1452 println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1453 println("for (int i = 0; i < len" + i + "; i++) {");
1454 println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1456 } else if (isList(paramType)) { // A list
1457 println("int len" + i + " = paramInt" + i + ".length;");
1458 println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1459 println("for (int i = 0; i < len" + i + "; i++) {");
1460 println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1462 } else { // Just one element
1463 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1471 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1473 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
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
1483 if (isArray(retType)) { // An array
1484 print(pureType + "[] retEnum = " + methodId + "(");
1485 } else if (isList(retType)) { // A list
1486 print("List<" + pureType + "> retEnum = " + methodId + "(");
1487 } else { // Just one element
1488 print(pureType + " retEnum = " + methodId + "(");
1495 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1497 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1499 // Strips off array "[]" for return type
1500 String pureType = getSimpleArrayType(getGenericType(retType));
1501 // Take the inner type of generic
1502 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1503 pureType = getGenericType(retType);
1504 if (isEnumClass(pureType)) {
1505 // Check if this is enum type
1506 if (isArray(retType)) { // An array
1507 println("int retLen = retEnum.length;");
1508 println("int[] retEnumVal = new int[retLen];");
1509 println("for (int i = 0; i < retLen; i++) {");
1510 println("retEnumVal[i] = retEnum[i].ordinal();");
1512 } else if (isList(retType)) { // A list
1513 println("int retLen = retEnum.size();");
1514 println("int[] retEnumVal = new int[retLen];");
1515 println("for (int i = 0; i < retLen; i++) {");
1516 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1518 } else { // Just one element
1519 println("int[] retEnumVal = new int[1];");
1520 println("retEnumVal[0] = retEnum.ordinal();");
1522 println("Object retObj = retEnumVal;");
1528 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1530 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1531 String method, InterfaceDecl intDecl) {
1533 // Iterate and find struct declarations - count number of params
1534 for (int i = 0; i < methParams.size(); i++) {
1535 String paramType = methPrmTypes.get(i);
1536 String param = methParams.get(i);
1537 String simpleType = getGenericType(paramType);
1538 if (isStructClass(simpleType)) {
1539 int members = getNumOfMembers(simpleType);
1540 print(Integer.toString(members) + "*");
1541 int methodNumId = intDecl.getMethodNumId(method);
1542 print("struct" + methodNumId + "Size" + i);
1545 if (i != methParams.size() - 1) {
1553 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1555 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1556 String param, String method, InterfaceDecl intDecl, int iVar) {
1558 // Get the struct declaration for this struct and generate initialization code
1559 StructDecl structDecl = getStructDecl(simpleType);
1560 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1561 List<String> members = structDecl.getMembers(simpleType);
1562 if (isArrayOrList(paramType, param)) { // An array or list
1563 int methodNumId = intDecl.getMethodNumId(method);
1564 String counter = "struct" + methodNumId + "Size" + iVar;
1565 println("for(int i = 0; i < " + counter + "; i++) {");
1567 if (isArrayOrList(paramType, param)) { // An array or list
1568 for (int i = 0; i < members.size(); i++) {
1569 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1570 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1571 println("paramClsGen[pos++] = null;");
1574 } else { // Just one struct element
1575 for (int i = 0; i < members.size(); i++) {
1576 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1577 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1578 println("paramClsGen[pos++] = null;");
1585 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1587 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1588 List<String> methPrmTypes, String method) {
1590 println("int objPos = 0;");
1591 for (int i = 0; i < methParams.size(); i++) {
1592 String paramType = methPrmTypes.get(i);
1593 String param = methParams.get(i);
1594 String simpleType = getGenericType(paramType);
1595 if (isStructClass(simpleType)) {
1596 int methodNumId = intDecl.getMethodNumId(method);
1597 String counter = "struct" + methodNumId + "Size" + i;
1599 if (isArray(param)) { // An array
1600 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1601 println("for(int i = 0; i < " + counter + "; i++) {");
1602 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1604 } else if (isList(paramType)) { // A list
1605 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1607 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1608 // Initialize members
1609 StructDecl structDecl = getStructDecl(simpleType);
1610 List<String> members = structDecl.getMembers(simpleType);
1611 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1612 if (isArrayOrList(paramType, param)) { // An array or list
1613 println("for(int i = 0; i < " + counter + "; i++) {");
1615 if (isArray(param)) { // An array
1616 for (int j = 0; j < members.size(); j++) {
1617 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1618 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1619 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1622 } else if (isList(paramType)) { // A list
1623 println(simpleType + " paramStructMem = new " + simpleType + "();");
1624 for (int j = 0; j < members.size(); j++) {
1625 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1626 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1627 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1629 println("paramStruct" + i + ".add(paramStructMem);");
1631 } else { // Just one struct element
1632 for (int j = 0; j < members.size(); j++) {
1633 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1634 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1635 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1639 // Take offsets of parameters
1640 println("int offset" + i +" = objPos++;");
1647 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1649 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1651 // Minimum retLen is 1 if this is a single struct object
1652 if (isArray(retType))
1653 println("int retLen = retStruct.length;");
1654 else if (isList(retType))
1655 println("int retLen = retStruct.size();");
1656 else // Just single struct object
1657 println("int retLen = 1;");
1658 println("Object retLenObj = retLen;");
1659 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1660 int numMem = getNumOfMembers(simpleType);
1661 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1662 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1663 println("int retPos = 0;");
1664 // Get the struct declaration for this struct and generate initialization code
1665 StructDecl structDecl = getStructDecl(simpleType);
1666 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1667 List<String> members = structDecl.getMembers(simpleType);
1668 if (isArray(retType)) { // An array or list
1669 println("for(int i = 0; i < retLen; i++) {");
1670 for (int i = 0; i < members.size(); i++) {
1671 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1672 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1673 print("retObj[retPos++] = retStruct[i].");
1674 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1678 } else if (isList(retType)) { // An array or list
1679 println("for(int i = 0; i < retLen; i++) {");
1680 for (int i = 0; i < members.size(); i++) {
1681 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1682 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1683 print("retObj[retPos++] = retStruct.get(i).");
1684 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1688 } else { // Just one struct element
1689 for (int i = 0; i < members.size(); i++) {
1690 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1691 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1692 print("retObj[retPos++] = retStruct.");
1693 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1702 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1704 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1705 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1706 boolean isStructMethod) {
1708 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1709 Map<Integer,String> mapStubParam = null;
1710 if (isCallbackMethod) {
1712 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1714 // Check if this is "void"
1715 String retType = intDecl.getMethodType(method);
1716 if (retType.equals("void")) {
1717 print(intDecl.getMethodId(method) + "(");
1718 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1719 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1720 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1721 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1722 } else { // We do have a return value
1723 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1725 for (int i = 0; i < methParams.size(); i++) {
1727 String paramType = methPrmTypes.get(i);
1728 if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1729 print(mapStubParam.get(i)); // Get the callback parameter
1730 } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1731 print(getEnumParam(paramType, methParams.get(i), i));
1732 } else if (isStructClass(getGenericType(paramType))) {
1733 print("paramStruct" + i);
1735 String prmType = checkAndGetArray(paramType, methParams.get(i));
1737 print("(" + prmType + ") paramObj[offset" + i + "]");
1739 print("(" + prmType + ") paramObj[" + i + "]");
1741 if (i != methParams.size() - 1)
1745 if (!retType.equals("void")) {
1746 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1747 checkAndWriteEnumRetConvJavaSkeleton(retType);
1748 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1749 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1750 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1751 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1753 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1755 if (isCallbackMethod) { // Catch exception if this is callback
1757 println(" catch(Exception ex) {");
1758 println("ex.printStackTrace();");
1759 println("throw new Error(\"Exception from callback object instantiation!\");");
1766 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1768 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1769 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1771 // Generate array of parameter objects
1772 boolean isCallbackMethod = false;
1773 Set<String> callbackType = new HashSet<String>();
1774 println("byte[] localMethodBytes = methodBytes;");
1775 println("rmiComm.setGetMethodBytes();");
1776 print("int paramLen = ");
1777 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1779 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1780 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1781 println("int pos = 0;");
1782 // Iterate again over the parameters
1783 for (int i = 0; i < methParams.size(); i++) {
1784 String paramType = methPrmTypes.get(i);
1785 String param = methParams.get(i);
1786 String simpleType = getGenericType(paramType);
1787 if (isStructClass(simpleType)) {
1788 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1790 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1791 if (callbackClasses.contains(prmType)) {
1792 isCallbackMethod = true;
1793 //callbackType = prmType;
1794 callbackType.add(prmType);
1795 println("paramCls[pos] = int[].class;");
1796 println("paramClsGen[pos++] = null;");
1797 } else { // Generate normal classes if it's not a callback object
1798 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1799 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1800 print("paramClsGen[pos++] = ");
1801 String prmTypeOth = methPrmTypes.get(i);
1802 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1803 println(getTypeOfGeneric(prmType)[0] + ".class;");
1809 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1810 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1811 // Write the return value part
1812 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1817 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1819 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1820 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1822 // Generate array of parameter objects
1823 boolean isCallbackMethod = false;
1824 Set<String> callbackType = new HashSet<String>();
1825 println("byte[] localMethodBytes = methodBytes;");
1826 println("rmiComm.setGetMethodBytes();");
1827 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1828 for (int i = 0; i < methParams.size(); i++) {
1830 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1831 if (callbackClasses.contains(paramType)) {
1832 isCallbackMethod = true;
1833 callbackType.add(paramType);
1834 print("int[].class");
1835 } else { // Generate normal classes if it's not a callback object
1836 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1837 print(getSimpleType(getEnumType(prmType)) + ".class");
1839 if (i != methParams.size() - 1)
1842 // Generate generic class if it's a generic type.. null otherwise
1843 print(" }, new Class<?>[] { ");
1844 for (int i = 0; i < methParams.size(); i++) {
1845 String prmType = methPrmTypes.get(i);
1846 if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1847 !isEnumClass(getGenericType(prmType)) &&
1848 !callbackClasses.contains(getGenericType(prmType)))
1849 print(getGenericType(prmType) + ".class");
1852 if (i != methParams.size() - 1)
1855 println(" }, localMethodBytes);");
1856 // Write the return value part
1857 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1862 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1864 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1866 // Use this set to handle two same methodIds
1867 Set<String> uniqueMethodIds = new HashSet<String>();
1868 for (String method : methods) {
1870 List<String> methParams = intDecl.getMethodParams(method);
1871 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1872 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1873 String methodId = intDecl.getMethodId(method);
1874 print("public void ___");
1875 String helperMethod = methodId;
1876 if (uniqueMethodIds.contains(methodId))
1877 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1879 uniqueMethodIds.add(methodId);
1880 String retType = intDecl.getMethodType(method);
1881 print(helperMethod + "(");
1882 boolean begin = true;
1883 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1884 String paramType = methPrmTypes.get(i);
1885 String param = methParams.get(i);
1886 String simpleType = getGenericType(paramType);
1887 if (isStructClass(simpleType)) {
1888 if (!begin) // Generate comma for not the beginning variable
1892 int methodNumId = intDecl.getMethodNumId(method);
1893 print("int struct" + methodNumId + "Size" + i);
1896 // Check if this is "void"
1897 if (retType.equals("void"))
1900 println(") throws IOException {");
1901 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1904 String methodId = intDecl.getMethodId(method);
1905 print("public void ___");
1906 String helperMethod = methodId;
1907 if (uniqueMethodIds.contains(methodId))
1908 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1910 uniqueMethodIds.add(methodId);
1911 // Check if this is "void"
1912 String retType = intDecl.getMethodType(method);
1913 if (retType.equals("void"))
1914 println(helperMethod + "() {");
1916 println(helperMethod + "() throws IOException {");
1917 // Now, write the helper body of skeleton!
1918 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1922 // Write method helper for structs
1923 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1928 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1930 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1931 InterfaceDecl intDecl) {
1933 // Use this set to handle two same methodIds
1934 for (String method : methods) {
1936 List<String> methParams = intDecl.getMethodParams(method);
1937 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1938 // Check for params with structs
1939 for (int i = 0; i < methParams.size(); i++) {
1940 String paramType = methPrmTypes.get(i);
1941 String param = methParams.get(i);
1942 String simpleType = getGenericType(paramType);
1943 if (isStructClass(simpleType)) {
1944 int methodNumId = intDecl.getMethodNumId(method);
1945 print("public int ___");
1946 String helperMethod = methodNumId + "struct" + i;
1947 println(helperMethod + "() {");
1948 // Now, write the helper body of skeleton!
1949 println("byte[] localMethodBytes = methodBytes;");
1950 println("rmiComm.setGetMethodBytes();");
1951 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1952 println("return (int) paramObj[0];");
1961 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1963 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1964 InterfaceDecl intDecl) {
1966 // Use this set to handle two same methodIds
1967 for (String method : methods) {
1969 List<String> methParams = intDecl.getMethodParams(method);
1970 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1971 // Check for params with structs
1972 for (int i = 0; i < methParams.size(); i++) {
1973 String paramType = methPrmTypes.get(i);
1974 String param = methParams.get(i);
1975 String simpleType = getGenericType(paramType);
1976 if (isStructClass(simpleType)) {
1977 int methodNumId = intDecl.getMethodNumId(method);
1978 print("public int ___");
1979 String helperMethod = methodNumId + "struct" + i;
1980 println(helperMethod + "(IoTRMIObject rmiObj) {");
1981 // Now, write the helper body of skeleton!
1982 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1983 println("return (int) paramObj[0];");
1992 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1994 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1996 // Use this set to handle two same methodIds
1997 for (String method : methods) {
1999 List<String> methParams = intDecl.getMethodParams(method);
2000 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2001 // Check for params with structs
2002 for (int i = 0; i < methParams.size(); i++) {
2003 String paramType = methPrmTypes.get(i);
2004 String param = methParams.get(i);
2005 String simpleType = getGenericType(paramType);
2006 if (isStructClass(simpleType)) {
2007 int methodNumId = intDecl.getMethodNumId(method);
2008 println("int struct" + methodNumId + "Size" + i + " = 0;");
2016 * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
2018 private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
2020 List<String> methParams = intDecl.getMethodParams(method);
2021 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2022 boolean structExist = false;
2023 boolean begin = true;
2024 // Check for params with structs
2025 for (int i = 0; i < methParams.size(); i++) {
2026 String paramType = methPrmTypes.get(i);
2027 String param = methParams.get(i);
2028 String simpleType = getGenericType(paramType);
2029 if (isStructClass(simpleType)) {
2035 int methodNumId = intDecl.getMethodNumId(method);
2036 print("struct" + methodNumId + "Size" + i + "Final");
2044 * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2046 private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2048 List<String> methParams = intDecl.getMethodParams(method);
2049 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2050 boolean structExist = false;
2051 boolean begin = true;
2052 // Check for params with structs
2053 for (int i = 0; i < methParams.size(); i++) {
2054 String paramType = methPrmTypes.get(i);
2055 String param = methParams.get(i);
2056 String simpleType = getGenericType(paramType);
2057 if (isStructClass(simpleType)) {
2063 int methodNumId = intDecl.getMethodNumId(method);
2064 print("struct" + methodNumId + "Size" + i);
2072 * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2074 private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2076 // Use this set to handle two same methodIds
2077 for (String method : methods) {
2079 List<String> methParams = intDecl.getMethodParams(method);
2080 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2081 // Check for params with structs
2082 for (int i = 0; i < methParams.size(); i++) {
2083 String paramType = methPrmTypes.get(i);
2084 String param = methParams.get(i);
2085 String simpleType = getGenericType(paramType);
2086 if (isStructClass(simpleType)) {
2087 int methodNumId = intDecl.getMethodNumId(method);
2089 String helperMethod = methodNumId + "struct" + i;
2090 String tempVar = "struct" + methodNumId + "Size" + i;
2091 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2092 print(tempVar + " = ___");
2093 println(helperMethod + "(); break;");
2101 * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2103 private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2105 // Use this set to handle two same methodIds
2106 for (String method : methods) {
2108 List<String> methParams = intDecl.getMethodParams(method);
2109 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2110 // Check for params with structs
2111 for (int i = 0; i < methParams.size(); i++) {
2112 String paramType = methPrmTypes.get(i);
2113 String param = methParams.get(i);
2114 String simpleType = getGenericType(paramType);
2115 if (isStructClass(simpleType)) {
2116 int methodNumId = intDecl.getMethodNumId(method);
2118 String helperMethod = methodNumId + "struct" + i;
2119 String tempVar = "struct" + methodNumId + "Size" + i;
2120 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2121 print(tempVar + " = ___");
2122 println(helperMethod + "(skel); break;");
2130 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2132 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2134 // Use this set to handle two same methodIds
2135 for (String method : methods) {
2137 List<String> methParams = intDecl.getMethodParams(method);
2138 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2139 // Check for params with structs
2140 for (int i = 0; i < methParams.size(); i++) {
2141 String paramType = methPrmTypes.get(i);
2142 String param = methParams.get(i);
2143 String simpleType = getGenericType(paramType);
2144 if (isStructClass(simpleType)) {
2145 int methodNumId = intDecl.getMethodNumId(method);
2147 String helperMethod = methodNumId + "struct" + i;
2148 String tempVar = "struct" + methodNumId + "Size" + i;
2149 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2150 print(tempVar + " = ___");
2151 println(helperMethod + "(rmiObj); break;");
2159 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2161 private void writeJavaMethodPermission(String intface) {
2163 // Get all the different stubs
2164 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2165 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2166 String newIntface = intMeth.getKey();
2167 int newObjectId = getNewIntfaceObjectId(newIntface);
2168 println("if (_objectId == objectId) {");
2169 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2170 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
2174 println("continue;");
2181 * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2183 private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2185 List<String> methParams = intDecl.getMethodParams(method);
2186 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2187 boolean structExist = false;
2188 boolean begin = true;
2189 // Check for params with structs
2190 for (int i = 0; i < methParams.size(); i++) {
2191 String paramType = methPrmTypes.get(i);
2192 String param = methParams.get(i);
2193 String simpleType = getGenericType(paramType);
2194 if (isStructClass(simpleType)) {
2196 int methodNumId = intDecl.getMethodNumId(method);
2197 println("final int struct" + methodNumId + "Size" + i +
2198 "Final = struct" + methodNumId + "Size" + i + ";");
2206 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2208 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2210 // Use this set to handle two same methodIds
2211 Set<String> uniqueMethodIds = new HashSet<String>();
2212 println("public void ___waitRequestInvokeMethod() throws IOException {");
2213 // Write variables here if we have callbacks or enums or structs
2214 writeCountVarStructSkeleton(methods, intDecl);
2215 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2216 println("while (true) {");
2217 println("if (!methodReceived.get()) {");
2218 println("continue;");
2220 println("methodBytes = rmiComm.getMethodBytes();");
2221 println("methodReceived.set(false);");
2222 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2223 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2224 // Generate permission check
2225 writeJavaMethodPermission(intface);
2226 println("switch (methodId) {");
2227 // Print methods and method Ids
2228 for (String method : methods) {
2229 String methodId = intDecl.getMethodId(method);
2230 int methodNumId = intDecl.getMethodNumId(method);
2231 println("case " + methodNumId + ":");
2232 // Check for stuct counters
2233 writeFinalInputCountVarStructSkeleton(method, intDecl);
2234 println("new Thread() {");
2235 println("public void run() {");
2238 String helperMethod = methodId;
2239 if (uniqueMethodIds.contains(methodId))
2240 helperMethod = helperMethod + methodNumId;
2242 uniqueMethodIds.add(methodId);
2243 print(helperMethod + "(");
2244 writeInputCountVarStructJavaSkeleton(method, intDecl);
2247 println("catch (Exception ex) {");
2248 println("ex.printStackTrace();");
2251 println("}.start();");
2254 String method = "___initCallBack()";
2255 writeMethodCallStructJavaSkeleton(methods, intDecl);
2256 println("default: ");
2257 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2265 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2267 private void writeReturnDidAlreadyInitWaitInvoke() {
2269 println("public boolean didAlreadyInitWaitInvoke() {");
2270 println("return didAlreadyInitWaitInvoke.get();");
2276 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2278 public void generateJavaSkeletonClass() throws IOException {
2280 // Create a new directory
2281 String path = createDirectories(dir, subdir);
2282 for (String intface : mapIntfacePTH.keySet()) {
2284 // Check if there is more than 1 class that uses the same interface
2285 List<String> drvList = mapInt2Drv.get(intface);
2286 for(int i = 0; i < drvList.size(); i++) {
2289 String driverClass = drvList.get(i);
2290 // Open a new file to write into
2291 String newSkelClass = intface + "_Skeleton";
2292 String packageClass = null;
2293 // Check if this interface is a callback class
2294 if(isCallbackClass(intface)) {
2295 packageClass = controllerClass;
2296 path = createDirectories(dir + "/" + subdir, controllerClass);
2298 packageClass = CODE_PREFIX + "." + driverClass;
2299 path = createDirectories(dir + "/" + subdir, driverClass);
2301 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2302 pw = new PrintWriter(new BufferedWriter(fw));
2303 // Pass in set of methods and get import classes
2304 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2305 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2306 List<String> methods = intDecl.getMethods();
2307 Set<String> importClasses = getImportClasses(methods, intDecl);
2308 List<String> stdImportClasses = getStandardJavaImportClasses();
2309 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2310 // Find out if there are callback objects
2311 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2312 boolean callbackExist = !callbackClasses.isEmpty();
2313 println("package " + packageClass + ";\n");
2314 printImportStatements(allImportClasses);
2315 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
2316 // Write class header
2317 println("public class " + newSkelClass + " implements " + intface + " {\n");
2319 writePropertiesJavaSkeleton(intface, intDecl);
2320 // Write constructor
2321 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2322 // Write constructor that is called when this object is a callback object
2323 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2324 // Write function to return didAlreadyInitWaitInvoke
2325 writeReturnDidAlreadyInitWaitInvoke();
2327 writeMethodJavaSkeleton(methods, intDecl);
2328 // Write method helper
2329 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2330 // Write waitRequestInvokeMethod() - main loop
2331 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2334 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2340 /*================================================================================
2344 *================================================================================/
2347 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2349 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2351 for (String method : methods) {
2353 List<String> methParams = intDecl.getMethodParams(method);
2354 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2355 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2356 intDecl.getMethodId(method) + "(");
2357 for (int i = 0; i < methParams.size(); i++) {
2358 // Check for params with driver class types and exchange it
2359 // with its remote interface
2360 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2361 paramType = checkAndGetCplusType(paramType);
2362 // Check for arrays - translate into vector in C++
2363 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2364 print(paramComplete);
2365 // Check if this is the last element (don't print a comma)
2366 if (i != methParams.size() - 1) {
2376 * HELPER: writeMethodCplusInterface() writes the method of the interface
2378 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2380 for (String method : methods) {
2382 List<String> methParams = intDecl.getMethodParams(method);
2383 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2384 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2385 intDecl.getMethodId(method) + "(");
2386 for (int i = 0; i < methParams.size(); i++) {
2387 // Check for params with driver class types and exchange it
2388 // with its remote interface
2389 String paramType = methPrmTypes.get(i);
2390 paramType = checkAndGetCplusType(paramType);
2391 // Check for arrays - translate into vector in C++
2392 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2393 print(paramComplete);
2394 // Check if this is the last element (don't print a comma)
2395 if (i != methParams.size() - 1) {
2405 * HELPER: generateEnumCplus() writes the enumeration declaration
2407 public void generateEnumCplus() throws IOException {
2409 // Create a new directory
2410 createDirectory(dir);
2411 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2412 for (String intface : mapIntfacePTH.keySet()) {
2413 // Get the right StructDecl
2414 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2415 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2416 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2417 // Iterate over enum declarations
2418 for (String enType : enumTypes) {
2419 // Open a new file to write into
2420 FileWriter fw = new FileWriter(path + "/" + enType + ".hpp");
2421 pw = new PrintWriter(new BufferedWriter(fw));
2422 // Write file headers
2423 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2424 println("#define _" + enType.toUpperCase() + "_HPP__");
2425 println("enum " + enType + " {");
2426 List<String> enumMembers = enumDecl.getMembers(enType);
2427 for (int i = 0; i < enumMembers.size(); i++) {
2429 String member = enumMembers.get(i);
2431 // Check if this is the last element (don't print a comma)
2432 if (i != enumMembers.size() - 1)
2440 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2447 * HELPER: generateStructCplus() writes the struct declaration
2449 public void generateStructCplus() throws IOException {
2451 // Create a new directory
2452 createDirectory(dir);
2453 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2454 for (String intface : mapIntfacePTH.keySet()) {
2455 // Get the right StructDecl
2456 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2457 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2458 List<String> structTypes = structDecl.getStructTypes();
2459 // Iterate over enum declarations
2460 for (String stType : structTypes) {
2461 // Open a new file to write into
2462 FileWriter fw = new FileWriter(path + "/" + stType + ".hpp");
2463 pw = new PrintWriter(new BufferedWriter(fw));
2464 // Write file headers
2465 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2466 println("#define _" + stType.toUpperCase() + "_HPP__");
2467 println("using namespace std;");
2468 println("struct " + stType + " {");
2469 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2470 List<String> structMembers = structDecl.getMembers(stType);
2471 for (int i = 0; i < structMembers.size(); i++) {
2473 String memberType = structMemberTypes.get(i);
2474 String member = structMembers.get(i);
2475 String structTypeC = checkAndGetCplusType(memberType);
2476 String structComplete = checkAndGetCplusArray(structTypeC, member);
2477 println(structComplete + ";");
2482 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2489 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2491 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2492 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2493 * The local interface has to be the input parameter for the stub and the stub
2494 * interface has to be the input parameter for the local class.
2496 public void generateCplusLocalInterfaces() throws IOException {
2498 // Create a new directory
2499 createDirectory(dir);
2500 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2501 for (String intface : mapIntfacePTH.keySet()) {
2502 // Open a new file to write into
2503 FileWriter fw = new FileWriter(path + "/" + intface + ".hpp");
2504 pw = new PrintWriter(new BufferedWriter(fw));
2505 // Write file headers
2506 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2507 println("#define _" + intface.toUpperCase() + "_HPP__");
2508 println("#include <iostream>");
2509 // Pass in set of methods and get include classes
2510 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2511 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2512 List<String> methods = intDecl.getMethods();
2513 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2514 printIncludeStatements(includeClasses); println("");
2515 println("using namespace std;\n");
2516 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2517 if (!intface.equals(mainClass)) // Forward declare if not main class
2518 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2519 println("class " + intface); println("{");
2522 writeMethodCplusLocalInterface(methods, intDecl);
2526 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2532 * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2534 private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2536 Set<String> isDefined = new HashSet<String>();
2537 for (String method : methods) {
2539 List<String> methParams = intDecl.getMethodParams(method);
2540 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2541 for (int i = 0; i < methParams.size(); i++) {
2542 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2543 // Check if this has callback object
2544 if (callbackClasses.contains(paramType)) {
2545 if (!isDefined.contains(paramType)) {
2547 println("class " + getStubInterface(paramType) + ";\n");
2549 println("class " + paramType + ";\n");
2550 isDefined.add(paramType);
2559 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2561 * For C++ we use virtual classe as interface
2563 public void generateCPlusInterfaces() throws IOException {
2565 // Create a new directory
2566 String path = createDirectories(dir, subdir);
2567 path = createDirectories(dir + "/" + subdir, VIRTUALS_DIRECTORY);
2568 for (String intface : mapIntfacePTH.keySet()) {
2570 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2571 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2573 // Open a new file to write into
2574 String newIntface = intMeth.getKey();
2575 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2576 pw = new PrintWriter(new BufferedWriter(fw));
2577 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2578 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2579 // Write file headers
2580 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2581 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2582 println("#include <iostream>");
2583 updateIntfaceObjIdMap(intface, newIntface);
2584 // Pass in set of methods and get import classes
2585 Set<String> methods = intMeth.getValue();
2586 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2587 printIncludeStatements(includeClasses); println("");
2588 println("using namespace std;\n");
2589 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2590 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2591 println("class " + newIntface);
2595 writeMethodCplusInterface(methods, intDecl);
2599 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2606 * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2608 private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2610 for (String method : methods) {
2612 List<String> methParams = intDecl.getMethodParams(method);
2613 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2614 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2615 intDecl.getMethodId(method) + "(");
2616 for (int i = 0; i < methParams.size(); i++) {
2618 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2619 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2620 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2621 print(methParamComplete);
2622 // Check if this is the last element (don't print a comma)
2623 if (i != methParams.size() - 1) {
2633 * HELPER: writeMethodCplusStub() writes the methods of the stub
2635 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2637 for (String method : methods) {
2639 List<String> methParams = intDecl.getMethodParams(method);
2640 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2641 // Print the mutex lock first
2642 int methodNumId = intDecl.getMethodNumId(method);
2643 String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2644 println("mutex " + mutexVar + ";");
2645 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2646 intDecl.getMethodId(method) + "(");
2647 boolean isCallbackMethod = false;
2648 Set<String> callbackType = new HashSet<String>();
2649 for (int i = 0; i < methParams.size(); i++) {
2651 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2652 // Check if this has callback object
2653 if (callbackClasses.contains(paramType)) {
2654 isCallbackMethod = true;
2655 //callbackType = paramType;
2656 callbackType.add(paramType);
2657 // Even if there're 2 callback arguments, we expect them to be of the same interface
2659 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2660 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2661 print(methParamComplete);
2662 // Check if this is the last element (don't print a comma)
2663 if (i != methParams.size() - 1) {
2668 println("lock_guard<mutex> guard(" + mutexVar + ");");
2669 if (isCallbackMethod)
2670 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2671 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2679 * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2681 private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2683 println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2684 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2685 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2686 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2687 println("rmiComm->decrementObjectIdCounter();");
2688 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2689 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2690 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2691 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter +
2692 ", skel" + counter +");");
2693 println("th" + counter + ".detach();");
2694 println("while(!skel" + counter + "->didInitWaitInvoke());");
2698 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2699 println("objIdSent" + counter + ".push_back(itId->second);");
2705 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2707 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2708 List<String> methPrmTypes, String method, Set<String> callbackType) {
2710 // Check if this is single object, array, or list of objects
2711 boolean isArrayOrList = false;
2712 String callbackParam = null;
2713 for (int i = 0; i < methParams.size(); i++) {
2714 String paramType = methPrmTypes.get(i);
2715 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2716 println("vector<int> objIdSent" + i + ";");
2717 String param = methParams.get(i);
2718 if (isArrayOrList(paramType, param)) { // Generate loop
2719 println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2720 writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2721 isArrayOrList = true;
2722 callbackParam = getSimpleIdentifier(param);
2724 writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2728 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2735 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2737 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2739 // Iterate and find enum declarations
2740 for (int i = 0; i < methParams.size(); i++) {
2741 String paramType = methPrmTypes.get(i);
2742 String param = methParams.get(i);
2743 if (isEnumClass(getGenericType(paramType))) {
2744 // Check if this is enum type
2745 if (isArrayOrList(paramType, param)) { // An array or vector
2746 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2747 println("vector<int> paramEnum" + i + "(len" + i + ");");
2748 println("for (int i = 0; i < len" + i + "; i++) {");
2749 println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2751 } else { // Just one element
2752 println("vector<int> paramEnum" + i + "(1);");
2753 println("paramEnum" + i + "[0] = (int) " + param + ";");
2761 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2763 private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2765 // Strips off array "[]" for return type
2766 String pureType = getSimpleArrayType(getGenericType(retType));
2767 // Take the inner type of generic
2768 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2769 pureType = getGenericType(retType);
2770 if (isEnumClass(pureType)) {
2771 // Check if this is enum type
2772 println("vector<int> retEnumInt;");
2773 println("void* retObj = &retEnumInt;");
2774 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2775 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2776 if (isArrayOrList(retType, retType)) { // An array or vector
2777 println("int retLen = retEnumInt.size();");
2778 println("vector<" + pureType + "> retVal(retLen);");
2779 println("for (int i = 0; i < retLen; i++) {");
2780 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2782 } else { // Just one element
2783 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2785 println("return retVal;");
2791 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2793 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2794 InterfaceDecl intDecl, String method) {
2796 // Iterate and find struct declarations
2797 for (int i = 0; i < methParams.size(); i++) {
2798 String paramType = methPrmTypes.get(i);
2799 String param = methParams.get(i);
2800 String simpleType = getGenericType(paramType);
2801 if (isStructClass(simpleType)) {
2802 // Check if this is enum type
2803 println("int numParam" + i + " = 1;");
2804 int methodNumId = intDecl.getMethodNumId(method);
2805 String helperMethod = methodNumId + "struct" + i;
2806 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2807 //println("string retTypeStruct" + i + " = \"void\";");
2808 println("string paramClsStruct" + i + "[] = { \"int\" };");
2809 print("int structLen" + i + " = ");
2810 if (isArrayOrList(paramType, param)) { // An array
2811 println(getSimpleArrayType(param) + ".size();");
2812 } else { // Just one element
2815 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2816 println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
2817 ", paramClsStruct" + i + ", paramObjStruct" + i +
2818 ", numParam" + i + ");\n");
2825 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2827 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2829 // Iterate and find struct declarations - count number of params
2830 for (int i = 0; i < methParams.size(); i++) {
2831 String paramType = methPrmTypes.get(i);
2832 String param = methParams.get(i);
2833 String simpleType = getGenericType(paramType);
2834 if (isStructClass(simpleType)) {
2835 int members = getNumOfMembers(simpleType);
2836 if (isArrayOrList(paramType, param)) { // An array or list
2837 String structLen = getSimpleIdentifier(param) + ".size()";
2838 print(members + "*" + structLen);
2840 print(Integer.toString(members));
2843 if (i != methParams.size() - 1) {
2851 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2853 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2855 // Get the struct declaration for this struct and generate initialization code
2856 StructDecl structDecl = getStructDecl(simpleType);
2857 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2858 List<String> members = structDecl.getMembers(simpleType);
2859 if (isArrayOrList(paramType, param)) { // An array or list
2860 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2862 if (isArrayOrList(paramType, param)) { // An array or list
2863 for (int i = 0; i < members.size(); i++) {
2864 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2865 println("paramCls[pos] = \"" + prmTypeC + "\";");
2866 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2867 print(getSimpleIdentifier(members.get(i)));
2871 } else { // Just one struct element
2872 for (int i = 0; i < members.size(); i++) {
2873 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2874 println("paramCls[pos] = \"" + prmTypeC + "\";");
2875 print("paramObj[pos++] = &" + param + ".");
2876 print(getSimpleIdentifier(members.get(i)));
2884 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2886 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2888 print("int numParam = ");
2889 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2891 println("void* paramObj[numParam];");
2892 println("string paramCls[numParam];");
2893 println("int pos = 0;");
2894 // Iterate again over the parameters
2895 for (int i = 0; i < methParams.size(); i++) {
2896 String paramType = methPrmTypes.get(i);
2897 String param = methParams.get(i);
2898 String simpleType = getGenericType(paramType);
2899 if (isStructClass(simpleType)) {
2900 writeStructMembersCplusStub(simpleType, paramType, param);
2901 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2902 println("paramCls[pos] = \"int\";");
2903 println("paramObj[pos++] = &___paramCB" + i + ";");
2905 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2906 println("paramCls[pos] = \"" + prmTypeC + "\";");
2907 print("paramObj[pos++] = &");
2908 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2917 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2919 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2921 // Get the struct declaration for this struct and generate initialization code
2922 StructDecl structDecl = getStructDecl(simpleType);
2923 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2924 List<String> members = structDecl.getMembers(simpleType);
2925 if (isArrayOrList(retType, retType)) { // An array or list
2926 println("for(int i = 0; i < retLen; i++) {");
2928 if (isArrayOrList(retType, retType)) { // An array or list
2929 for (int i = 0; i < members.size(); i++) {
2930 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2931 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2932 println(" = retParam" + i + "[i];");
2935 } else { // Just one struct element
2936 for (int i = 0; i < members.size(); i++) {
2937 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2938 print("structRet." + getSimpleIdentifier(members.get(i)));
2939 println(" = retParam" + i + ";");
2942 println("return structRet;");
2947 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2949 private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2951 // Minimum retLen is 1 if this is a single struct object
2952 println("int retLen = 0;");
2953 println("void* retLenObj = { &retLen };");
2954 // Handle the returned struct!!!
2955 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2956 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2957 int numMem = getNumOfMembers(simpleType);
2958 println("int numRet = " + numMem + "*retLen;");
2959 println("string retCls[numRet];");
2960 println("void* retObj[numRet];");
2961 StructDecl structDecl = getStructDecl(simpleType);
2962 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2963 List<String> members = structDecl.getMembers(simpleType);
2965 if (isArrayOrList(retType, retType)) { // An array or list
2966 for (int i = 0; i < members.size(); i++) {
2967 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2968 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2969 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2971 } else { // Just one struct element
2972 for (int i = 0; i < members.size(); i++) {
2973 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2974 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2975 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2978 println("int retPos = 0;");
2979 // Get the struct declaration for this struct and generate initialization code
2980 if (isArrayOrList(retType, retType)) { // An array or list
2981 println("for(int i = 0; i < retLen; i++) {");
2982 for (int i = 0; i < members.size(); i++) {
2983 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2984 println("retCls[retPos] = \"" + prmTypeC + "\";");
2985 println("retObj[retPos++] = &retParam" + i + "[i];");
2988 } else { // Just one struct element
2989 for (int i = 0; i < members.size(); i++) {
2990 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2991 println("retCls[retPos] = \"" + prmTypeC + "\";");
2992 println("retObj[retPos++] = &retParam" + i + ";");
2995 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2996 if (isArrayOrList(retType, retType)) { // An array or list
2997 println("vector<" + simpleType + "> structRet(retLen);");
2999 println(simpleType + " structRet;");
3000 writeStructRetMembersCplusStub(simpleType, retType);
3005 * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
3007 private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
3009 println("// Waiting for return value");
3010 int methodNumId = intDecl.getMethodNumId(method);
3011 println("while (!retValueReceived" + methodNumId + ");");
3012 println(getReturnValue);
3013 println("retValueReceived" + methodNumId + " = false;");
3014 println("didGetReturnBytes.exchange(true);\n");
3019 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
3021 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
3022 List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
3024 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
3025 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
3026 String retType = intDecl.getMethodType(method);
3027 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
3028 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
3029 // Generate array of parameter types
3030 if (isStructPresent(methParams, methPrmTypes)) {
3031 writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
3033 println("int numParam = " + methParams.size() + ";");
3034 print("string paramCls[] = { ");
3035 for (int i = 0; i < methParams.size(); i++) {
3036 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3037 if (checkCallbackType(paramType, callbackType)) {
3040 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3041 print("\"" + paramTypeC + "\"");
3043 // Check if this is the last element (don't print a comma)
3044 if (i != methParams.size() - 1) {
3049 // Generate array of parameter objects
3050 print("void* paramObj[] = { ");
3051 for (int i = 0; i < methParams.size(); i++) {
3052 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3053 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3054 print("&___paramCB" + i);
3056 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3057 // Check if this is the last element (don't print a comma)
3058 if (i != methParams.size() - 1) {
3064 // Check if this is "void"
3065 if (retType.equals("void")) {
3066 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3067 } else { // We do have a return value
3068 // Generate array of parameter types
3069 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3070 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3072 // Check if the return value NONPRIMITIVES
3073 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3074 checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3076 //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3077 if (isArrayOrList(retType,retType))
3078 println(checkAndGetCplusType(retType) + " retVal;");
3080 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3082 println("void* retObj = &retVal;");
3083 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3084 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3085 println("return retVal;");
3093 * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3095 private void writePropertiesCplusPermission(String intface) {
3097 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3098 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3099 String newIntface = intMeth.getKey();
3100 int newObjectId = getNewIntfaceObjectId(newIntface);
3101 println("static set<int> set" + newObjectId + "Allowed;");
3106 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3108 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
3109 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3111 println("IoTRMIComm *rmiComm;");
3112 // Get the object Id
3113 Integer objId = mapIntfaceObjId.get(intface);
3114 println("int objectId = " + objId + ";");
3115 println("// Synchronization variables");
3116 for (String method : methods) {
3117 // Generate AtomicBooleans for methods that have return values
3118 String returnType = intDecl.getMethodType(method);
3119 int methodNumId = intDecl.getMethodNumId(method);
3120 if (!returnType.equals("void")) {
3121 println("bool retValueReceived" + methodNumId + " = false;");
3129 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3131 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
3132 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3134 println(newStubClass + "::" + newStubClass +
3135 "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3136 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3137 // Register the AtomicBoolean variables
3138 for (String method : methods) {
3139 // Generate AtomicBooleans for methods that have return values
3140 String returnType = intDecl.getMethodType(method);
3141 int methodNumId = intDecl.getMethodNumId(method);
3142 if (!returnType.equals("void")) {
3143 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3146 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3152 * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3154 private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
3155 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3157 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3158 println("rmiComm = _rmiComm;");
3159 println("objectId = _objectId;");
3160 // Register the AtomicBoolean variables
3161 for (String method : methods) {
3162 // Generate AtomicBooleans for methods that have return values
3163 String returnType = intDecl.getMethodType(method);
3164 int methodNumId = intDecl.getMethodNumId(method);
3165 if (!returnType.equals("void")) {
3166 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3174 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3176 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3178 println(newStubClass + "::~" + newStubClass + "() {");
3179 println("if (rmiComm != NULL) {");
3180 println("delete rmiComm;");
3181 println("rmiComm = NULL;");
3189 * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3191 public void generateCPlusStubClassesHpp() throws IOException {
3193 // Create a new directory
3194 String path = createDirectories(dir, subdir);
3195 for (String intface : mapIntfacePTH.keySet()) {
3197 // Check if there is more than 1 class that uses the same interface
3198 List<String> drvList = mapInt2Drv.get(intface);
3199 for(int i = 0; i < drvList.size(); i++) {
3201 String driverClass = drvList.get(i);
3202 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3203 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3204 // Open a new file to write into
3205 String newIntface = intMeth.getKey();
3206 String newStubClass = newIntface + "_Stub";
3207 // Check if this interface is a callback class
3208 if(isCallbackClass(intface))
3209 path = createDirectories(dir + "/" + subdir, driverClass);
3211 path = createDirectories(dir + "/" + subdir, controllerClass);
3212 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3213 pw = new PrintWriter(new BufferedWriter(fw));
3214 // Write file headers
3215 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3216 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3217 println("#include <iostream>");
3218 // Find out if there are callback objects
3219 Set<String> methods = intMeth.getValue();
3220 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3221 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3222 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3223 boolean callbackExist = !callbackClasses.isEmpty();
3224 println("#include <thread>");
3225 println("#include <mutex>");
3226 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3227 printIncludeStatements(stdIncludeClasses); println("");
3228 println("#include \"" + newIntface + ".hpp\""); println("");
3229 println("using namespace std;"); println("");
3230 println("class " + newStubClass + " : public " + newIntface); println("{");
3231 println("private:\n");
3232 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3233 println("public:\n");
3234 // Add default constructor and destructor
3235 println(newStubClass + "();");
3237 println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3238 println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3239 println("~" + newStubClass + "();");
3241 writeMethodDeclCplusStub(methods, intDecl);
3242 print("}"); println(";");
3245 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3253 * writeStubExternalCFunctions() generate external functions for .so file
3255 public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3257 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3258 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3259 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " +
3260 "*((int*) params[3]), (bool*) params[4]);");
3262 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3263 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3264 println("delete obj;");
3266 println("extern \"C\" void init" + newStubClass + "(void* t) {");
3272 * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3274 public void generateCPlusStubClassesCpp() throws IOException {
3276 // Create a new directory
3277 String path = createDirectories(dir, subdir);
3278 for (String intface : mapIntfacePTH.keySet()) {
3280 // Check if there is more than 1 class that uses the same interface
3281 List<String> drvList = mapInt2Drv.get(intface);
3282 for(int i = 0; i < drvList.size(); i++) {
3284 String driverClass = drvList.get(i);
3285 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3286 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3287 // Open a new file to write into
3288 String newIntface = intMeth.getKey();
3289 String newStubClass = newIntface + "_Stub";
3290 // Check if this interface is a callback class
3291 if(isCallbackClass(intface))
3292 path = createDirectories(dir + "/" + subdir, driverClass);
3294 path = createDirectories(dir + "/" + subdir, controllerClass);
3295 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3296 pw = new PrintWriter(new BufferedWriter(fw));
3297 // Write file headers
3298 println("#include <iostream>");
3299 // Find out if there are callback objects
3300 Set<String> methods = intMeth.getValue();
3301 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3302 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3303 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3304 boolean callbackExist = !callbackClasses.isEmpty();
3305 println("#include \"" + newStubClass + ".hpp\""); println("");
3306 for(String str: callbackClasses) {
3307 if (intface.equals(mainClass))
3308 println("#include \"" + str + "_Skeleton.cpp\"\n");
3310 println("#include \"" + str + "_Skeleton.hpp\"\n");
3312 println("using namespace std;"); println("");
3313 // Add default constructor and destructor
3314 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3315 writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3316 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3318 writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3319 // Write external functions for .so file
3320 writeStubExternalCFunctions(newStubClass);
3321 // TODO: Remove this later
3322 if (intface.equals(mainClass)) {
3323 println("int main() {");
3324 println("return 0;");
3328 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3336 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3338 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3340 println(intface + " *mainObj;");
3341 println("IoTRMIComm *rmiComm;");
3342 println("char* methodBytes;");
3343 println("int methodLen;");
3344 Integer objId = mapIntfaceObjId.get(intface);
3345 println("int objectId = " + objId + ";");
3346 // Keep track of object Ids of all stubs registered to this interface
3347 writePropertiesCplusPermission(intface);
3348 println("// Synchronization variables");
3349 println("bool methodReceived = false;");
3350 println("bool didAlreadyInitWaitInvoke = false;");
3356 * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3358 private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3361 println("int " + newSkelClass + "::objIdCnt = 0;");
3366 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3368 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3370 // Keep track of object Ids of all stubs registered to this interface
3371 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3372 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3373 String newIntface = intMeth.getKey();
3374 int newObjectId = getNewIntfaceObjectId(newIntface);
3375 print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3376 Set<String> methodIds = intMeth.getValue();
3378 for (String methodId : methodIds) {
3379 int methodNumId = intDecl.getMethodNumId(methodId);
3380 print(Integer.toString(methodNumId));
3381 // Check if this is the last element (don't print a comma)
3382 if (i != methodIds.size() - 1) {
3393 * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3395 private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3397 // Use this set to handle two same methodIds
3398 for (String method : methods) {
3399 List<String> methParams = intDecl.getMethodParams(method);
3400 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3401 // Check for params with structs
3402 for (int i = 0; i < methParams.size(); i++) {
3403 String paramType = methPrmTypes.get(i);
3404 String param = methParams.get(i);
3405 String simpleType = getGenericType(paramType);
3406 if (isStructClass(simpleType)) {
3407 int methodNumId = intDecl.getMethodNumId(method);
3408 String helperMethod = methodNumId + "struct" + i;
3409 int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3410 // Iterate over interfaces to give permissions to
3411 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3412 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3413 String newIntface = intMeth.getKey();
3414 int newObjectId = getNewIntfaceObjectId(newIntface);
3415 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3424 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3426 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3428 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3429 println("bool _bResult = false;");
3430 println("mainObj = _mainObj;");
3431 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3432 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3433 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3434 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3435 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3436 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3437 println("th1.join();");
3443 * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3445 private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3447 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3448 println("bool _bResult = false;");
3449 println("mainObj = _mainObj;");
3450 println("rmiComm = _rmiComm;");
3451 println("objectId = _objectId;");
3452 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3453 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3459 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3461 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3463 println(newSkelClass + "::~" + newSkelClass + "() {");
3464 println("if (rmiComm != NULL) {");
3465 println("delete rmiComm;");
3466 println("rmiComm = NULL;");
3474 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3476 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3478 if (methodType.equals("void"))
3479 print("mainObj->" + methodId + "(");
3481 print("return mainObj->" + methodId + "(");
3482 for (int i = 0; i < methParams.size(); i++) {
3484 print(getSimpleIdentifier(methParams.get(i)));
3485 // Check if this is the last element (don't print a comma)
3486 if (i != methParams.size() - 1) {
3495 * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3497 private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3498 Set<String> callbackClasses) {
3500 for (String method : methods) {
3502 List<String> methParams = intDecl.getMethodParams(method);
3503 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3504 String methodId = intDecl.getMethodId(method);
3505 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3506 print(methodType + " " + methodId + "(");
3507 boolean isCallbackMethod = false;
3508 String callbackType = null;
3509 for (int i = 0; i < methParams.size(); i++) {
3511 String origParamType = methPrmTypes.get(i);
3512 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3513 isCallbackMethod = true;
3514 callbackType = origParamType;
3516 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3517 String methPrmType = checkAndGetCplusType(paramType);
3518 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3519 print(methParamComplete);
3520 // Check if this is the last element (don't print a comma)
3521 if (i != methParams.size() - 1) {
3531 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3533 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3535 for (String method : methods) {
3537 List<String> methParams = intDecl.getMethodParams(method);
3538 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3539 String methodId = intDecl.getMethodId(method);
3540 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3541 print(methodType + " " + newSkelClass + "::" + methodId + "(");
3542 for (int i = 0; i < methParams.size(); i++) {
3544 String origParamType = methPrmTypes.get(i);
3545 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3546 String methPrmType = checkAndGetCplusType(paramType);
3547 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3548 print(methParamComplete);
3549 // Check if this is the last element (don't print a comma)
3550 if (i != methParams.size() - 1) {
3555 // Now, write the body of skeleton!
3556 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3563 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3565 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3567 for (int i = 0; i < methParams.size(); i++) {
3568 String paramType = methPrmTypes.get(i);
3569 String param = methParams.get(i);
3570 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3571 println("vector<int> numStubIdArray" + i + ";");
3577 * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3579 private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
3581 println(exchParamType + "* newStub" + counter + " = NULL;");
3582 println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
3583 println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
3584 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
3585 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
3586 println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
3587 println("rmiComm->decrementObjectIdCounter();");
3590 println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
3596 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3598 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3600 // Iterate over callback objects
3601 for (int i = 0; i < methParams.size(); i++) {
3602 String paramType = methPrmTypes.get(i);
3603 String param = methParams.get(i);
3604 // Generate a loop if needed
3605 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3606 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3607 if (isArrayOrList(paramType, param)) {
3608 println("vector<" + exchParamType + "*> stub" + i + ";");
3609 println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3610 println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
3611 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3612 println("stub" + i + ".push_back(newStub" + i + ");");
3615 println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
3616 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3617 println(exchParamType + "* stub" + i + " = newStub" + i + ";");
3625 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3627 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3629 // Iterate and find enum declarations
3630 for (int i = 0; i < methParams.size(); i++) {
3631 String paramType = methPrmTypes.get(i);
3632 String param = methParams.get(i);
3633 String simpleType = getGenericType(paramType);
3634 if (isEnumClass(simpleType)) {
3635 // Check if this is enum type
3636 if (isArrayOrList(paramType, param)) { // An array
3637 println("int len" + i + " = paramEnumInt" + i + ".size();");
3638 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3639 println("for (int i=0; i < len" + i + "; i++) {");
3640 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3642 } else { // Just one element
3643 println(simpleType + " paramEnum" + i + ";");
3644 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3652 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3654 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3656 // Strips off array "[]" for return type
3657 String pureType = getSimpleArrayType(getGenericType(retType));
3658 // Take the inner type of generic
3659 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3660 pureType = getGenericType(retType);
3661 if (isEnumClass(pureType)) {
3662 // Check if this is enum type
3664 if (isArrayOrList(retType, retType)) { // An array
3665 println("int retLen = retEnum.size();");
3666 println("vector<int> retEnumInt(retLen);");
3667 println("for (int i=0; i < retLen; i++) {");
3668 println("retEnumInt[i] = (int) retEnum[i];");
3670 } else { // Just one element
3671 println("vector<int> retEnumInt(1);");
3672 println("retEnumInt[0] = (int) retEnum;");
3679 * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3681 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3682 Set<String> callbackClasses, String methodId) {
3684 print(methodId + "(");
3685 for (int i = 0; i < methParams.size(); i++) {
3686 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3687 if (callbackClasses.contains(paramType))
3689 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3690 print("paramEnum" + i);
3691 else if (isStructClass(getGenericType(paramType))) // Struct type
3692 print("paramStruct" + i);
3694 print(getSimpleIdentifier(methParams.get(i)));
3695 if (i != methParams.size() - 1) {
3704 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3706 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3707 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
3708 String methodId, Set<String> callbackClasses) {
3710 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3711 if (isCallbackMethod)
3712 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3713 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3714 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3715 // Check if this is "void"
3716 String retType = intDecl.getMethodType(method);
3717 // Check if this is "void"
3718 if (retType.equals("void")) {
3719 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3720 } else { // We do have a return value
3721 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3722 print(checkAndGetCplusType(retType) + " retEnum = ");
3723 else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3724 print(checkAndGetCplusType(retType) + " retStruct = ");
3726 print(checkAndGetCplusType(retType) + " retVal = ");
3727 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3728 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3729 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3730 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3731 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3732 println("void* retObj = &retEnumInt;");
3734 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3735 println("void* retObj = &retVal;");
3736 String retTypeC = checkAndGetCplusType(retType);
3737 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3738 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3740 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3746 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3748 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3749 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3751 // Generate array of parameter types
3752 boolean isCallbackMethod = false;
3753 Set<String> callbackType = new HashSet<String>();
3754 print("string paramCls[] = { ");
3755 for (int i = 0; i < methParams.size(); i++) {
3756 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3757 if (callbackClasses.contains(paramType)) {
3758 isCallbackMethod = true;
3759 callbackType.add(paramType);
3761 } else { // Generate normal classes if it's not a callback object
3762 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3763 print("\"" + paramTypeC + "\"");
3765 if (i != methParams.size() - 1) {
3770 println("int numParam = " + methParams.size() + ";");
3771 if (isCallbackMethod)
3772 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3773 // Generate parameters
3774 for (int i = 0; i < methParams.size(); i++) {
3775 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3776 if (!callbackClasses.contains(paramType)) {
3777 String methParamType = methPrmTypes.get(i);
3778 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
3779 // Check if this is enum type
3780 println("vector<int> paramEnumInt" + i + ";");
3782 String methPrmType = checkAndGetCplusType(methParamType);
3783 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3784 println(methParamComplete + ";");
3788 // Generate array of parameter objects
3789 print("void* paramObj[] = { ");
3790 for (int i = 0; i < methParams.size(); i++) {
3791 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3792 if (callbackClasses.contains(paramType))
3793 print("&numStubIdArray" + i);
3794 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3795 print("¶mEnumInt" + i);
3797 print("&" + getSimpleIdentifier(methParams.get(i)));
3798 if (i != methParams.size() - 1) {
3803 // Write the return value part
3804 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3805 callbackType, methodId, callbackClasses);
3810 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3812 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3813 String param, String method, InterfaceDecl intDecl, int iVar) {
3815 // Get the struct declaration for this struct and generate initialization code
3816 StructDecl structDecl = getStructDecl(simpleType);
3817 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3818 List<String> members = structDecl.getMembers(simpleType);
3819 int methodNumId = intDecl.getMethodNumId(method);
3820 String counter = "struct" + methodNumId + "Size" + iVar;
3822 if (isArrayOrList(paramType, param)) { // An array or list
3823 for (int i = 0; i < members.size(); i++) {
3824 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3825 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3826 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3828 } else { // Just one struct element
3829 for (int i = 0; i < members.size(); i++) {
3830 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3831 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3832 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3835 if (isArrayOrList(paramType, param)) { // An array or list
3836 println("for(int i = 0; i < " + counter + "; i++) {");
3838 if (isArrayOrList(paramType, param)) { // An array or list
3839 for (int i = 0; i < members.size(); i++) {
3840 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3841 println("paramCls[pos] = \"" + prmTypeC + "\";");
3842 println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
3845 } else { // Just one struct element
3846 for (int i = 0; i < members.size(); i++) {
3847 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3848 println("paramCls[pos] = \"" + prmTypeC + "\";");
3849 println("paramObj[pos++] = ¶m" + iVar + i + ";");
3856 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3858 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3859 List<String> methPrmTypes, String method) {
3861 for (int i = 0; i < methParams.size(); i++) {
3862 String paramType = methPrmTypes.get(i);
3863 String param = methParams.get(i);
3864 String simpleType = getGenericType(paramType);
3865 if (isStructClass(simpleType)) {
3866 int methodNumId = intDecl.getMethodNumId(method);
3867 String counter = "struct" + methodNumId + "Size" + i;
3869 if (isArrayOrList(paramType, param)) { // An array or list
3870 println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3872 println(simpleType + " paramStruct" + i + ";");
3873 // Initialize members
3874 StructDecl structDecl = getStructDecl(simpleType);
3875 List<String> members = structDecl.getMembers(simpleType);
3876 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3877 if (isArrayOrList(paramType, param)) { // An array or list
3878 println("for(int i = 0; i < " + counter + "; i++) {");
3879 for (int j = 0; j < members.size(); j++) {
3880 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3881 println(" = param" + i + j + "[i];");
3884 } else { // Just one struct element
3885 for (int j = 0; j < members.size(); j++) {
3886 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3887 println(" = param" + i + j + ";");
3896 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3898 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3900 // Minimum retLen is 1 if this is a single struct object
3901 if (isArrayOrList(retType, retType))
3902 println("int retLen = retStruct.size();");
3903 else // Just single struct object
3904 println("int retLen = 1;");
3905 println("void* retLenObj = &retLen;");
3906 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3907 int numMem = getNumOfMembers(simpleType);
3908 println("int numRetObj = " + numMem + "*retLen;");
3909 println("string retCls[numRetObj];");
3910 println("void* retObj[numRetObj];");
3911 println("int retPos = 0;");
3912 // Get the struct declaration for this struct and generate initialization code
3913 StructDecl structDecl = getStructDecl(simpleType);
3914 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3915 List<String> members = structDecl.getMembers(simpleType);
3916 if (isArrayOrList(retType, retType)) { // An array or list
3917 println("for(int i = 0; i < retLen; i++) {");
3918 for (int i = 0; i < members.size(); i++) {
3919 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3920 println("retCls[retPos] = \"" + prmTypeC + "\";");
3921 print("retObj[retPos++] = &retStruct[i].");
3922 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3926 } else { // Just one struct element
3927 for (int i = 0; i < members.size(); i++) {
3928 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3929 println("retCls[retPos] = \"" + prmTypeC + "\";");
3930 print("retObj[retPos++] = &retStruct.");
3931 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3940 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3942 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3943 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3945 // Generate array of parameter objects
3946 boolean isCallbackMethod = false;
3947 Set<String> callbackType = new HashSet<String>();
3948 print("int numParam = ");
3949 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3951 println("string paramCls[numParam];");
3952 println("void* paramObj[numParam];");
3953 println("int pos = 0;");
3954 // Iterate again over the parameters
3955 for (int i = 0; i < methParams.size(); i++) {
3956 String paramType = methPrmTypes.get(i);
3957 String param = methParams.get(i);
3958 String simpleType = getGenericType(paramType);
3959 if (isStructClass(simpleType)) {
3960 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3962 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3963 if (callbackClasses.contains(prmType)) {
3964 isCallbackMethod = true;
3965 callbackType.add(prmType);
3966 println("vector<int> numStubIdArray" + i + ";");
3967 println("paramCls[pos] = \"int*\";");
3968 println("paramObj[pos++] = &numStubIdArray" + i + ";");
3969 } else { // Generate normal classes if it's not a callback object
3970 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3971 if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
3972 println("vector<int> paramEnumInt" + i + ";");
3974 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3975 println(methParamComplete + ";");
3977 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3978 println("paramCls[pos] = \"" + prmTypeC + "\";");
3979 if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3980 println("paramObj[pos++] = ¶mEnumInt" + i + ";");
3982 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3986 // Write the return value part
3987 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3988 callbackType, methodId, callbackClasses);
3993 * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
3995 private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3997 // Use this set to handle two same methodIds
3998 Set<String> uniqueMethodIds = new HashSet<String>();
3999 for (String method : methods) {
4001 List<String> methParams = intDecl.getMethodParams(method);
4002 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4003 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4004 String methodId = intDecl.getMethodId(method);
4006 String helperMethod = methodId;
4007 if (uniqueMethodIds.contains(methodId))
4008 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4010 uniqueMethodIds.add(methodId);
4011 String retType = intDecl.getMethodType(method);
4012 print(helperMethod + "(");
4013 boolean begin = true;
4014 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4015 String paramType = methPrmTypes.get(i);
4016 String param = methParams.get(i);
4017 String simpleType = getGenericType(paramType);
4018 if (isStructClass(simpleType)) {
4019 if (!begin) // Generate comma for not the beginning variable
4023 int methodNumId = intDecl.getMethodNumId(method);
4024 print("int struct" + methodNumId + "Size" + i);
4027 println(", " + newSkelClass + "* skel);");
4029 String methodId = intDecl.getMethodId(method);
4031 String helperMethod = methodId;
4032 if (uniqueMethodIds.contains(methodId))
4033 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4035 uniqueMethodIds.add(methodId);
4036 // Check if this is "void"
4037 String retType = intDecl.getMethodType(method);
4038 println(helperMethod + "(" + newSkelClass + "* skel);");
4041 // Write method helper for structs
4042 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
4047 * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
4049 private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods,
4050 InterfaceDecl intDecl, String newSkelClass) {
4052 // Use this set to handle two same methodIds
4053 for (String method : methods) {
4055 List<String> methParams = intDecl.getMethodParams(method);
4056 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4057 // Check for params with structs
4058 for (int i = 0; i < methParams.size(); i++) {
4059 String paramType = methPrmTypes.get(i);
4060 String param = methParams.get(i);
4061 String simpleType = getGenericType(paramType);
4062 if (isStructClass(simpleType)) {
4063 int methodNumId = intDecl.getMethodNumId(method);
4065 String helperMethod = methodNumId + "struct" + i;
4066 println(helperMethod + "(" + newSkelClass + "* skel);");
4074 * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4076 private void writeMethodBytesCopy() {
4078 println("char* localMethodBytes = new char[methodLen];");
4079 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4080 println("didGetMethodBytes.exchange(true);");
4085 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4087 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4088 Set<String> callbackClasses, String newSkelClass) {
4090 // Use this set to handle two same methodIds
4091 Set<String> uniqueMethodIds = new HashSet<String>();
4092 for (String method : methods) {
4094 List<String> methParams = intDecl.getMethodParams(method);
4095 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4096 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4097 String methodId = intDecl.getMethodId(method);
4098 print("void " + newSkelClass + "::___");
4099 String helperMethod = methodId;
4100 if (uniqueMethodIds.contains(methodId))
4101 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4103 uniqueMethodIds.add(methodId);
4104 String retType = intDecl.getMethodType(method);
4105 print(helperMethod + "(");
4106 boolean begin = true;
4107 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4108 String paramType = methPrmTypes.get(i);
4109 String param = methParams.get(i);
4110 String simpleType = getGenericType(paramType);
4111 if (isStructClass(simpleType)) {
4112 if (!begin) // Generate comma for not the beginning variable
4116 int methodNumId = intDecl.getMethodNumId(method);
4117 print("int struct" + methodNumId + "Size" + i);
4120 println(", " + newSkelClass + "* skel) {");
4121 writeMethodBytesCopy();
4122 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4123 println("delete[] localMethodBytes;");
4126 String methodId = intDecl.getMethodId(method);
4127 print("void " + newSkelClass + "::___");
4128 String helperMethod = methodId;
4129 if (uniqueMethodIds.contains(methodId))
4130 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4132 uniqueMethodIds.add(methodId);
4133 // Check if this is "void"
4134 String retType = intDecl.getMethodType(method);
4135 println(helperMethod + "(" + newSkelClass + "* skel) {");
4136 writeMethodBytesCopy();
4137 // Now, write the helper body of skeleton!
4138 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4139 println("delete[] localMethodBytes;");
4143 // Write method helper for structs
4144 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4149 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4151 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
4152 InterfaceDecl intDecl, String newSkelClass) {
4154 // Use this set to handle two same methodIds
4155 for (String method : methods) {
4157 List<String> methParams = intDecl.getMethodParams(method);
4158 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4159 // Check for params with structs
4160 for (int i = 0; i < methParams.size(); i++) {
4161 String paramType = methPrmTypes.get(i);
4162 String param = methParams.get(i);
4163 String simpleType = getGenericType(paramType);
4164 if (isStructClass(simpleType)) {
4165 int methodNumId = intDecl.getMethodNumId(method);
4166 print("int " + newSkelClass + "::___");
4167 String helperMethod = methodNumId + "struct" + i;
4168 println(helperMethod + "(" + newSkelClass + "* skel) {");
4169 // Now, write the helper body of skeleton!
4170 writeMethodBytesCopy();
4171 println("string paramCls[] = { \"int\" };");
4172 println("int numParam = 1;");
4173 println("int param0 = 0;");
4174 println("void* paramObj[] = { ¶m0 };");
4175 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4176 println("return param0;");
4177 println("delete[] localMethodBytes;");
4186 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4188 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
4189 InterfaceDecl intDecl) {
4191 // Use this set to handle two same methodIds
4192 for (String method : methods) {
4194 List<String> methParams = intDecl.getMethodParams(method);
4195 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4196 // Check for params with structs
4197 for (int i = 0; i < methParams.size(); i++) {
4198 String paramType = methPrmTypes.get(i);
4199 String param = methParams.get(i);
4200 String simpleType = getGenericType(paramType);
4201 if (isStructClass(simpleType)) {
4202 int methodNumId = intDecl.getMethodNumId(method);
4204 String helperMethod = methodNumId + "struct" + i;
4205 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4206 // Now, write the helper body of skeleton!
4207 println("string paramCls[] = { \"int\" };");
4208 println("int numParam = 1;");
4209 println("int param0 = 0;");
4210 println("void* paramObj[] = { ¶m0 };");
4211 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4212 println("return param0;");
4221 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4223 private void writeCplusMethodPermission(String intface) {
4225 // Get all the different stubs
4226 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4227 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4228 String newIntface = intMeth.getKey();
4229 int newObjectId = getNewIntfaceObjectId(newIntface);
4230 println("if (_objectId == objectId) {");
4231 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4232 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
4237 println("continue;");
4244 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4246 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4247 boolean callbackExist, String intface, String newSkelClass) {
4249 // Use this set to handle two same methodIds
4250 Set<String> uniqueMethodIds = new HashSet<String>();
4251 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4252 // Write variables here if we have callbacks or enums or structs
4253 writeCountVarStructSkeleton(methods, intDecl);
4254 println("skel->didAlreadyInitWaitInvoke = true;");
4255 println("while (true) {");
4256 println("if (!methodReceived) {");
4257 println("continue;");
4259 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4260 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4261 println("methodReceived = false;");
4262 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4263 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4264 // Generate permission check
4265 writeCplusMethodPermission(intface);
4266 println("switch (methodId) {");
4267 // Print methods and method Ids
4268 for (String method : methods) {
4269 String methodId = intDecl.getMethodId(method);
4270 int methodNumId = intDecl.getMethodNumId(method);
4271 println("case " + methodNumId + ": {");
4272 print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4273 String helperMethod = methodId;
4274 if (uniqueMethodIds.contains(methodId))
4275 helperMethod = helperMethod + methodNumId;
4277 uniqueMethodIds.add(methodId);
4278 print(helperMethod + ", skel, ");
4279 boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4283 println("th" + methodNumId + ".detach(); break;");
4286 writeMethodCallStructCplusSkeleton(methods, intDecl);
4287 println("default: ");
4288 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4297 * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4299 public void generateCplusSkeletonClassHpp() throws IOException {
4301 // Create a new directory
4302 String path = createDirectories(dir, subdir);
4303 for (String intface : mapIntfacePTH.keySet()) {
4305 // Check if there is more than 1 class that uses the same interface
4306 List<String> drvList = mapInt2Drv.get(intface);
4307 for(int i = 0; i < drvList.size(); i++) {
4309 // Open a new file to write into
4310 String newSkelClass = intface + "_Skeleton";
4312 String driverClass = drvList.get(i);
4313 // Check if this interface is a callback class
4314 if(isCallbackClass(intface))
4315 path = createDirectories(dir + "/" + subdir, controllerClass);
4317 path = createDirectories(dir + "/" + subdir, driverClass);
4318 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4319 pw = new PrintWriter(new BufferedWriter(fw));
4320 // Write file headers
4321 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4322 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4323 println("#include <iostream>");
4324 println("#include \"" + intface + ".hpp\"\n");
4325 // Pass in set of methods and get import classes
4326 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4327 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4328 List<String> methods = intDecl.getMethods();
4329 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4330 printIncludeStatements(stdIncludeClasses); println("");
4331 println("using namespace std;\n");
4332 // Find out if there are callback objects
4333 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4334 boolean callbackExist = !callbackClasses.isEmpty();
4335 // Write class header
4336 println("class " + newSkelClass + " : public " + intface); println("{");
4337 println("private:\n");
4339 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4340 println("public:\n");
4341 // Write constructors
4342 println(newSkelClass + "();");
4343 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4344 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4345 // Write deconstructor
4346 println("~" + newSkelClass + "();");
4347 // Write method declarations
4348 println("bool didInitWaitInvoke();");
4349 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4350 // Write method helper declarations
4351 writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
4352 // Write waitRequestInvokeMethod() declaration - main loop
4353 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4355 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4358 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4364 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4366 private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4368 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4369 println("return didAlreadyInitWaitInvoke;");
4375 * writeSkelExternalCFunctions() generate external functions for .so file
4377 public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4379 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4380 println("// Args: *_mainObj, int _portSend, int _portRecv");
4381 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
4383 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4384 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4385 println("delete obj;");
4387 println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4393 * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4395 public void generateCplusSkeletonClassCpp() throws IOException {
4397 // Create a new directory
4398 String path = createDirectories(dir, subdir);
4399 for (String intface : mapIntfacePTH.keySet()) {
4401 // Check if there is more than 1 class that uses the same interface
4402 List<String> drvList = mapInt2Drv.get(intface);
4403 for(int i = 0; i < drvList.size(); i++) {
4405 // Open a new file to write into
4406 String newSkelClass = intface + "_Skeleton";
4408 String driverClass = drvList.get(i);
4409 // Check if this interface is a callback class
4410 if(isCallbackClass(intface))
4411 path = createDirectories(dir + "/" + subdir, controllerClass);
4413 path = createDirectories(dir + "/" + subdir, driverClass);
4414 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4415 pw = new PrintWriter(new BufferedWriter(fw));
4416 // Write file headers
4417 println("#include <iostream>");
4418 println("#include \"" + newSkelClass + ".hpp\"\n");
4419 // Pass in set of methods and get import classes
4420 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4421 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4422 List<String> methods = intDecl.getMethods();
4423 // Find out if there are callback objects
4424 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4425 boolean callbackExist = !callbackClasses.isEmpty();
4426 for(String str: callbackClasses) {
4427 if (intface.equals(mainClass))
4428 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4430 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4432 println("using namespace std;\n");
4433 // Write constructor
4434 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4435 // Write callback constructor
4436 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4437 // Write deconstructor
4438 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4439 // Write didInitWaitInvoke() to return bool
4440 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4442 writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
4443 // Write method helper
4444 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4445 // Write waitRequestInvokeMethod() - main loop
4446 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4447 // Write external functions for .so file
4448 writeSkelExternalCFunctions(newSkelClass, intface);
4449 // TODO: Remove this later
4450 if (intface.equals(mainClass)) {
4451 println("int main() {");
4452 println("return 0;");
4456 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4463 * generateInitializer() generate initializer based on type
4465 public String generateCplusInitializer(String type) {
4467 // Generate dummy returns for now
4468 if (type.equals("short")||
4469 type.equals("int") ||
4470 type.equals("long") ||
4471 type.equals("float")||
4472 type.equals("double")) {
4475 } else if ( type.equals("String") ||
4476 type.equals("string")) {
4479 } else if ( type.equals("char") ||
4480 type.equals("byte")) {
4483 } else if ( type.equals("boolean")) {
4493 * setDirectory() sets a new directory for stub files
4495 public void setDirectory(String _subdir) {
4502 * printUsage() prints the usage of this compiler
4504 public static void printUsage() {
4506 System.out.println();
4507 System.out.println("Vigilia interface and stub compiler version 1.0");
4508 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4509 System.out.println("All rights reserved.");
4510 System.out.println("Usage:");
4511 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4512 System.out.println("\t\tDisplay this help texts\n\n");
4513 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4514 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4515 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4516 System.out.println("Options:");
4517 System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
4518 System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
4519 System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
4520 System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
4521 System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
4522 System.out.println();
4527 * parseFile() prepares Lexer and Parser objects, then parses the file
4529 public static ParseNode parseFile(String file) {
4531 ParseNode pn = null;
4533 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4534 ScannerBuffer lexer =
4535 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4536 Parser parse = new Parser(lexer,csf);
4537 pn = (ParseNode) parse.parse().value;
4538 } catch (Exception e) {
4539 e.printStackTrace();
4540 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4548 * Basic helper functions
4551 boolean newline=true;
4554 private void print(String str) {
4557 if (str.equals("}"))
4559 for(int i=0; i<tab; i++)
4569 * This function converts Java to C++ type for compilation
4571 private String convertType(String type) {
4573 if (mapPrimitives.containsKey(type))
4574 return mapPrimitives.get(type);
4581 * A collection of methods with print-to-file functionality
4583 private void println(String str) {
4586 if (str.contains("}") && !str.contains("{"))
4588 for(int i=0; i<tab; i++)
4597 private void updatetabbing(String str) {
4599 tablevel+=count(str,'{')-count(str,'}');
4603 private int count(String str, char key) {
4604 char[] array = str.toCharArray();
4606 for(int i=0; i<array.length; i++) {
4607 if (array[i] == key)
4614 private void createDirectory(String dirName) {
4616 File file = new File(dirName);
4617 if (!file.exists()) {
4619 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4621 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4624 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4629 // Create a directory and possibly a sub directory
4630 private String createDirectories(String dir, String subdir) {
4633 createDirectory(path);
4634 if (subdir != null) {
4635 path = path + "/" + subdir;
4636 createDirectory(path);
4642 // Inserting array members into a Map object
4643 // that maps arrKey to arrVal objects
4644 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4646 for(int i = 0; i < arrKey.length; i++) {
4648 map.put(arrKey[i], arrVal[i]);
4653 // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4654 // Throw an error if the new interface is not found!
4655 // Basically the compiler needs to parse the policy (and requires) files for callback class first
4656 private int getNewIntfaceObjectId(String newIntface) {
4658 int retObjId = mapNewIntfaceObjId.get(newIntface);
4663 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4664 private ParamCategory getParamCategory(String paramType) {
4666 if (mapPrimitives.containsKey(paramType)) {
4667 return ParamCategory.PRIMITIVES;
4668 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4669 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4670 return ParamCategory.NONPRIMITIVES;
4671 } else if (isEnumClass(paramType)) {
4672 return ParamCategory.ENUM;
4673 } else if (isStructClass(paramType)) {
4674 return ParamCategory.STRUCT;
4676 return ParamCategory.USERDEFINED;
4680 // Return full class name for non-primitives to generate Java import statements
4681 // e.g. java.util.Set for Set
4682 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4684 return mapNonPrimitivesJava.get(paramNonPrimitives);
4688 // Return full class name for non-primitives to generate Cplus include statements
4689 // e.g. #include <set> for Set
4690 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4692 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4696 // Get simple types, e.g. HashSet for HashSet<...>
4697 // Basically strip off the "<...>"
4698 private String getSimpleType(String paramType) {
4700 // Check if this is generics
4701 if(paramType.contains("<")) {
4702 String[] type = paramType.split("<");
4709 // Generate a set of standard classes for import statements
4710 private List<String> getStandardJavaIntfaceImportClasses() {
4712 List<String> importClasses = new ArrayList<String>();
4713 // Add the standard list first
4714 importClasses.add("java.util.List");
4715 importClasses.add("java.util.ArrayList");
4717 return importClasses;
4721 // Generate a set of standard classes for import statements
4722 private List<String> getStandardJavaImportClasses() {
4724 List<String> importClasses = new ArrayList<String>();
4725 // Add the standard list first
4726 importClasses.add("java.io.IOException");
4727 importClasses.add("java.util.List");
4728 importClasses.add("java.util.ArrayList");
4729 importClasses.add("java.util.Arrays");
4730 importClasses.add("java.util.Map");
4731 importClasses.add("java.util.HashMap");
4732 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4733 importClasses.add("iotrmi.Java.IoTRMIComm");
4734 importClasses.add("iotrmi.Java.IoTRMICommClient");
4735 importClasses.add("iotrmi.Java.IoTRMICommServer");
4736 importClasses.add("iotrmi.Java.IoTRMIUtil");
4738 return importClasses;
4742 // Generate a set of standard classes for import statements
4743 private List<String> getStandardCplusIncludeClasses() {
4745 List<String> importClasses = new ArrayList<String>();
4746 // Add the standard list first
4747 importClasses.add("<vector>");
4748 importClasses.add("<set>");
4749 importClasses.add("\"IoTRMIComm.hpp\"");
4750 importClasses.add("\"IoTRMICommClient.hpp\"");
4751 importClasses.add("\"IoTRMICommServer.hpp\"");
4753 return importClasses;
4757 // Combine all classes for import statements
4758 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4760 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4761 // Iterate over the list of import classes
4762 for (String str : libClasses) {
4763 if (!allLibClasses.contains(str)) {
4764 allLibClasses.add(str);
4767 return allLibClasses;
4772 // Generate a set of classes for import statements
4773 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4775 Set<String> importClasses = new HashSet<String>();
4776 for (String method : methods) {
4777 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4778 for (String paramType : methPrmTypes) {
4780 String simpleType = getSimpleType(paramType);
4781 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4782 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4786 return importClasses;
4790 // Handle and return the correct enum declaration
4791 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4792 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4794 // Strips off array "[]" for return type
4795 String pureType = getSimpleArrayType(type);
4796 // Take the inner type of generic
4797 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4798 pureType = getTypeOfGeneric(type)[0];
4799 if (isEnumClass(pureType)) {
4800 String enumType = intDecl.getInterface() + "." + type;
4807 // Handle and return the correct type
4808 private String getEnumParam(String type, String param, int i) {
4810 // Strips off array "[]" for return type
4811 String pureType = getSimpleArrayType(type);
4812 // Take the inner type of generic
4813 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4814 pureType = getTypeOfGeneric(type)[0];
4815 if (isEnumClass(pureType)) {
4816 String enumParam = "paramEnum" + i;
4823 // Handle and return the correct enum declaration translate into int[]
4824 private String getEnumType(String type) {
4826 // Strips off array "[]" for return type
4827 String pureType = getSimpleArrayType(type);
4828 // Take the inner type of generic
4829 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4830 pureType = getGenericType(type);
4831 if (isEnumClass(pureType)) {
4832 String enumType = "int[]";
4838 // Handle and return the correct enum declaration translate into int* for C
4839 private String getEnumCplusClsType(String type) {
4841 // Strips off array "[]" for return type
4842 String pureType = getSimpleArrayType(type);
4843 // Take the inner type of generic
4844 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4845 pureType = getGenericType(type);
4846 if (isEnumClass(pureType)) {
4847 String enumType = "int*";
4854 // Handle and return the correct struct declaration
4855 private String getStructType(String type) {
4857 // Strips off array "[]" for return type
4858 String pureType = getSimpleArrayType(type);
4859 // Take the inner type of generic
4860 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4861 pureType = getGenericType(type);
4862 if (isStructClass(pureType)) {
4863 String structType = "int";
4870 // Check if this an enum declaration
4871 private boolean isEnumClass(String type) {
4873 // Just iterate over the set of interfaces
4874 for (String intface : mapIntfacePTH.keySet()) {
4875 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4876 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4877 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4878 if (setEnumDecl.contains(type))
4885 // Check if this an struct declaration
4886 private boolean isStructClass(String type) {
4888 // Just iterate over the set of interfaces
4889 for (String intface : mapIntfacePTH.keySet()) {
4890 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4891 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4892 List<String> listStructDecl = structDecl.getStructTypes();
4893 if (listStructDecl.contains(type))
4900 // Return a struct declaration
4901 private StructDecl getStructDecl(String type) {
4903 // Just iterate over the set of interfaces
4904 for (String intface : mapIntfacePTH.keySet()) {
4905 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4906 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4907 List<String> listStructDecl = structDecl.getStructTypes();
4908 if (listStructDecl.contains(type))
4915 // Return number of members (-1 if not found)
4916 private int getNumOfMembers(String type) {
4918 // Just iterate over the set of interfaces
4919 for (String intface : mapIntfacePTH.keySet()) {
4920 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4921 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4922 List<String> listStructDecl = structDecl.getStructTypes();
4923 if (listStructDecl.contains(type))
4924 return structDecl.getNumOfMembers(type);
4930 // Generate a set of classes for include statements
4931 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4933 Set<String> includeClasses = new HashSet<String>();
4934 for (String method : methods) {
4936 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4937 List<String> methParams = intDecl.getMethodParams(method);
4938 for (int i = 0; i < methPrmTypes.size(); i++) {
4940 String genericType = getGenericType(methPrmTypes.get(i));
4941 String simpleType = getSimpleType(methPrmTypes.get(i));
4942 String param = methParams.get(i);
4943 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4944 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4945 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4947 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4948 // For original interface, we need it exchanged... not for stub interfaces
4950 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4951 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4953 //includeClasses.add("\"" + simpleType + ".hpp\"");
4954 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4957 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4958 includeClasses.add("\"" + genericType + ".hpp\"");
4960 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4961 includeClasses.add("\"" + genericType + ".hpp\"");
4963 if (param.contains("[]")) {
4964 // Check if this is array for C++; translate into vector
4965 includeClasses.add("<vector>");
4969 return includeClasses;
4973 // Generate a set of callback classes
4974 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4976 Set<String> callbackClasses = new HashSet<String>();
4977 for (String method : methods) {
4979 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4980 List<String> methParams = intDecl.getMethodParams(method);
4981 for (int i = 0; i < methPrmTypes.size(); i++) {
4983 String type = methPrmTypes.get(i);
4984 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4985 callbackClasses.add(type);
4986 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4987 // Can be a List<...> of callback objects ...
4988 String genericType = getTypeOfGeneric(type)[0];
4989 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4990 callbackClasses.add(type);
4995 return callbackClasses;
4999 // Check if this is a callback class
5000 private boolean isCallbackClass(String className) {
5002 Set<String> intfaceSet = mapIntDeclHand.keySet();
5003 for(String intface : intfaceSet) {
5005 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5006 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
5007 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
5008 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
5009 Set<String> methods = intMeth.getValue();
5010 for (String method : methods) {
5012 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
5013 List<String> methParams = intDecl.getMethodParams(method);
5014 for (int i = 0; i < methPrmTypes.size(); i++) {
5016 String type = methPrmTypes.get(i);
5017 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
5018 // Final check to see if this is the searched class
5019 if (type.equals(className))
5021 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
5022 // Can be a List<...> of callback objects ...
5023 String genericType = getTypeOfGeneric(type)[0];
5024 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
5025 if (type.equals(className))
5038 // Print import statements into file
5039 private void printImportStatements(Collection<String> importClasses) {
5041 for(String cls : importClasses) {
5042 println("import " + cls + ";");
5047 // Print include statements into file
5048 private void printIncludeStatements(Collection<String> includeClasses) {
5050 for(String cls : includeClasses) {
5051 println("#include " + cls);
5056 // Get the C++ version of a non-primitive type
5057 // e.g. set for Set and map for Map
5058 // Input nonPrimitiveType has to be generics in format
5059 private String[] getTypeOfGeneric(String nonPrimitiveType) {
5061 // Handle <, >, and , for 2-type generic/template
5062 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
5067 // Gets generic type inside "<" and ">"
5068 private String getGenericType(String type) {
5070 // Handle <, >, and , for 2-type generic/template
5071 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
5072 String[] substr = type.split("<")[1].split(">")[0].split(",");
5079 // This helper function strips off array declaration, e.g. int[] becomes int
5080 private String getSimpleArrayType(String type) {
5082 // Handle [ for array declaration
5083 String substr = type;
5084 if (type.contains("[]")) {
5085 substr = type.split("\\[\\]")[0];
5091 // This helper function strips off array declaration, e.g. D[] becomes D
5092 private String getSimpleIdentifier(String ident) {
5094 // Handle [ for array declaration
5095 String substr = ident;
5096 if (ident.contains("[]")) {
5097 substr = ident.split("\\[\\]")[0];
5103 // Checks and gets type in C++
5104 private String checkAndGetCplusType(String paramType) {
5106 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
5107 return convertType(paramType);
5108 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
5110 // Check for generic/template format
5111 if (paramType.contains("<") && paramType.contains(">")) {
5113 String genericClass = getSimpleType(paramType);
5114 String genericType = getGenericType(paramType);
5115 String cplusTemplate = null;
5116 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
5117 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
5118 cplusTemplate = cplusTemplate + "<" + genericType + "*>";
5120 cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
5122 return cplusTemplate;
5124 return getNonPrimitiveCplusClass(paramType);
5125 } else if(paramType.contains("[]")) { // Array type (used for return type only)
5126 String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
5128 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5129 return paramType + "*";
5131 // Just return it as is if it's not non-primitives
5136 // Detect array declaration, e.g. int A[],
5137 // then generate "int A[]" in C++ as "vector<int> A"
5138 private String checkAndGetCplusArray(String paramType, String param) {
5140 String paramComplete = null;
5141 // Check for array declaration
5142 if (param.contains("[]")) {
5143 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5145 // Just return it as is if it's not an array
5146 paramComplete = paramType + " " + param;
5148 return paramComplete;
5152 // Detect array declaration, e.g. int A[],
5153 // then generate "int A[]" in C++ as "vector<int> A"
5154 // This method just returns the type
5155 private String checkAndGetCplusArrayType(String paramType) {
5157 String paramTypeRet = null;
5158 // Check for array declaration
5159 if (paramType.contains("[]")) {
5160 String type = paramType.split("\\[\\]")[0];
5161 paramTypeRet = checkAndGetCplusType(type) + "[]";
5162 } else if (paramType.contains("vector")) {
5163 // Just return it as is if it's not an array
5164 String type = paramType.split("<")[1].split(">")[0];
5165 paramTypeRet = checkAndGetCplusType(type) + "[]";
5167 paramTypeRet = paramType;
5169 return paramTypeRet;
5173 // Detect array declaration, e.g. int A[],
5174 // then generate "int A[]" in C++ as "vector<int> A"
5175 // This method just returns the type
5176 private String checkAndGetCplusArrayType(String paramType, String param) {
5178 String paramTypeRet = null;
5179 // Check for array declaration
5180 if (param.contains("[]")) {
5181 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5182 } else if (paramType.contains("vector")) {
5183 // Just return it as is if it's not an array
5184 String type = paramType.split("<")[1].split(">")[0];
5185 paramTypeRet = checkAndGetCplusType(type) + "[]";
5187 paramTypeRet = paramType;
5189 return paramTypeRet;
5193 // Return the class type for class resolution (for return value)
5194 // - Check and return C++ array class, e.g. int A[] into int*
5195 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5196 private String checkAndGetCplusRetClsType(String paramType) {
5198 String paramTypeRet = null;
5199 // Check for array declaration
5200 if (paramType.contains("[]")) {
5201 String type = paramType.split("\\[\\]")[0];
5202 paramTypeRet = getSimpleArrayType(type) + "*";
5203 } else if (paramType.contains("<") && paramType.contains(">")) {
5204 // Just return it as is if it's not an array
5205 String type = paramType.split("<")[1].split(">")[0];
5206 paramTypeRet = "vector<" + getGenericType(type) + ">";
5208 paramTypeRet = paramType;
5210 return paramTypeRet;
5214 // Return the class type for class resolution (for method arguments)
5215 // - Check and return C++ array class, e.g. int A[] into int*
5216 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5217 private String checkAndGetCplusArgClsType(String paramType, String param) {
5219 String paramTypeRet = getEnumCplusClsType(paramType);
5220 if (!paramTypeRet.equals(paramType))
5221 // Just return if it is an enum type
5222 // Type will still be the same if it's not an enum type
5223 return paramTypeRet;
5225 // Check for array declaration
5226 if (param.contains("[]")) {
5227 paramTypeRet = getSimpleArrayType(paramType) + "*";
5228 } else if (paramType.contains("<") && paramType.contains(">")) {
5229 // Just return it as is if it's not an array
5230 String type = paramType.split("<")[1].split(">")[0];
5231 paramTypeRet = "vector<" + getGenericType(type) + ">";
5233 paramTypeRet = paramType;
5235 return paramTypeRet;
5239 // Detect array declaration, e.g. int A[],
5240 // then generate type "int[]"
5241 private String checkAndGetArray(String paramType, String param) {
5243 String paramTypeRet = null;
5244 // Check for array declaration
5245 if (param.contains("[]")) {
5246 paramTypeRet = paramType + "[]";
5248 // Just return it as is if it's not an array
5249 paramTypeRet = paramType;
5251 return paramTypeRet;
5255 // Is array or list?
5256 private boolean isArrayOrList(String paramType, String param) {
5258 // Check for array declaration
5261 else if (isList(paramType))
5269 // For return type we use retType as input parameter
5270 private boolean isArray(String param) {
5272 // Check for array declaration
5273 if (param.contains("[]"))
5281 private boolean isList(String paramType) {
5283 // Check for array declaration
5284 if (paramType.contains("List"))
5291 // Get the right type for a callback object
5292 private String checkAndGetParamClass(String paramType) {
5294 // Check if this is generics
5295 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5296 return exchangeParamType(paramType);
5297 } else if (isList(paramType) &&
5298 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5299 return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5305 // Returns the other interface for type-checking purposes for USERDEFINED
5306 // classes based on the information provided in multiple policy files
5307 // e.g. return CameraWithXXX instead of Camera
5308 private String exchangeParamType(String intface) {
5310 // Param type that's passed is the interface name we need to look for
5311 // in the map of interfaces, based on available policy files.
5312 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5313 if (decHandler != null) {
5314 // We've found the required interface policy files
5315 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5316 Set<String> setExchInt = reqDecl.getInterfaces();
5317 if (setExchInt.size() == 1) {
5318 Iterator iter = setExchInt.iterator();
5319 return (String) iter.next();
5321 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5322 ". Only one new interface can be declared if the object " + intface +
5323 " needs to be passed in as an input parameter!\n");
5326 // NULL value - this means policy files missing
5327 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5328 "... Please provide the necessary policy files for user-defined types." +
5329 " If this is an array please type the brackets after the variable name," +
5330 " e.g. \"String str[]\", not \"String[] str\"." +
5331 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5332 " supports List/ArrayList (Java) or list (C++).\n");
5337 public static void main(String[] args) throws Exception {
5339 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5340 if ((args.length == 0 ||
5341 args[0].equals("-help") ||
5342 args[0].equals("--help")||
5343 args[0].equals("-h"))) {
5345 IoTCompiler.printUsage();
5347 } else if (args.length > 1) {
5349 IoTCompiler comp = new IoTCompiler();
5351 //boolean driverDefined = false;
5352 boolean controllerDefined = false;
5354 if (!controllerDefined && args[i].equals("-cont")) {
5355 comp.setControllerClass(args[i+1]);
5356 controllerDefined = true;
5359 // Parse main policy file
5360 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5361 // Parse "requires" policy file
5362 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5363 // Get interface name
5364 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5365 comp.setDataStructures(intface, pnPol, pnReq);
5366 comp.getMethodsForIntface(intface);
5368 if (args[i].equals("-drv")) {
5369 comp.setDriverClass(intface, args[i+1]);
5372 throw new Error("IoTCompiler: ERROR - driver class name is needed for the interface: " + intface + "\n");
5373 // 1) Check if this is the last option before "-java" or "-cplus"
5374 // 2) Check if this is really the last option
5375 } while(!args[i].equals("-java") &&
5376 !args[i].equals("-cplus") &&
5378 // Controller class name needs to be defined at least once
5379 if (!controllerDefined)
5380 throw new Error("IoTCompiler: ERROR - controller class name has not been specified!\n");
5382 // Generate everything if we don't see "-java" or "-cplus"
5383 if (i == args.length) {
5384 comp.generateEnumJava();
5385 comp.generateStructJava();
5386 comp.generateJavaLocalInterfaces();
5387 comp.generateJavaInterfaces();
5388 comp.generateJavaStubClasses();
5389 comp.generateJavaSkeletonClass();
5390 comp.generateEnumCplus();
5391 comp.generateStructCplus();
5392 comp.generateCplusLocalInterfaces();
5393 comp.generateCPlusInterfaces();
5394 comp.generateCPlusStubClassesHpp();
5395 comp.generateCPlusStubClassesCpp();
5396 comp.generateCplusSkeletonClassHpp();
5397 comp.generateCplusSkeletonClassCpp();
5399 // Check other options
5400 while(i < args.length) {
5402 if (!args[i].equals("-java") &&
5403 !args[i].equals("-cplus")) {
5404 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5406 if (i + 1 < args.length) {
5407 comp.setDirectory(args[i+1]);
5409 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5411 if (args[i].equals("-java")) {
5412 comp.generateEnumJava();
5413 comp.generateStructJava();
5414 comp.generateJavaLocalInterfaces();
5415 comp.generateJavaInterfaces();
5416 comp.generateJavaStubClasses();
5417 comp.generateJavaSkeletonClass();
5419 comp.generateEnumCplus();
5420 comp.generateStructCplus();
5421 comp.generateCplusLocalInterfaces();
5422 comp.generateCPlusInterfaces();
5423 comp.generateCPlusStubClassesHpp();
5424 comp.generateCPlusStubClassesCpp();
5425 comp.generateCplusSkeletonClassHpp();
5426 comp.generateCplusSkeletonClassCpp();
5433 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5434 IoTCompiler.printUsage();
5435 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");