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,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 CODE_PREFIX = "iotcode";
75 private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
78 private enum ParamCategory {
80 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
81 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
83 STRUCT, // Struct type
84 USERDEFINED // Assumed as driver classes
91 public IoTCompiler() {
93 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
94 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
95 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
96 mapInt2NewIntName = new HashMap<String,String>();
97 mapInt2Drv = new HashMap<String,String>();
98 mapIntfaceObjId = new HashMap<String,Integer>();
99 mapNewIntfaceObjId = new HashMap<String,Integer>();
100 mapPrimitives = new HashMap<String,String>();
101 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
102 mapNonPrimitivesJava = new HashMap<String,String>();
103 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
104 mapNonPrimitivesCplus = new HashMap<String,String>();
105 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
106 mapPortCount = new HashMap<String,Integer>();
108 dir = OUTPUT_DIRECTORY;
111 controllerClass = null;
116 * setDriverClass() sets the name of the driver class.
118 public void setDriverClass(String _driverClass, String _intface) {
120 mapInt2Drv.put(_driverClass, _intface);
124 * getDriverClass() sets the name of the driver class.
126 public String getDriverClass(String _intface) {
128 return mapInt2Drv.get(_intface);
133 * setControllerClass() sets the name of the controller class.
135 public void setControllerClass(String _controllerClass) {
137 controllerClass = _controllerClass;
142 * setDataStructures() sets parse tree and other data structures based on policy files.
144 * It also generates parse tree (ParseTreeHandler) and
145 * copies useful information from parse tree into
146 * InterfaceDecl, CapabilityDecl, and RequiresDecl
148 * Additionally, the data structure handles are
149 * returned from tree-parsing for further process.
151 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
153 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
154 DeclarationHandler decHandler = new DeclarationHandler();
155 // Process ParseNode and generate Declaration objects
157 ptHandler.processInterfaceDecl();
158 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
159 decHandler.addInterfaceDecl(origInt, intDecl);
161 ptHandler.processCapabilityDecl();
162 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
163 decHandler.addCapabilityDecl(origInt, capDecl);
165 ptHandler.processRequiresDecl();
166 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
167 decHandler.addRequiresDecl(origInt, reqDecl);
169 ptHandler.processEnumDecl();
170 EnumDecl enumDecl = ptHandler.getEnumDecl();
171 decHandler.addEnumDecl(origInt, enumDecl);
173 ptHandler.processStructDecl();
174 StructDecl structDecl = ptHandler.getStructDecl();
175 decHandler.addStructDecl(origInt, structDecl);
177 mapIntfacePTH.put(origInt, ptHandler);
178 mapIntDeclHand.put(origInt, decHandler);
179 // Set object Id counter to 0 for each interface
180 mapIntfaceObjId.put(origInt, countObjId++);
185 * getMethodsForIntface() reads for methods in the data structure
187 * It is going to give list of methods for a certain interface
188 * based on the declaration of capabilities.
190 public void getMethodsForIntface(String origInt) {
192 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
193 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
194 // Get set of new interfaces, e.g. CameraWithCaptureAndData
195 // Generate this new interface with all the methods it needs
196 // from different capabilities it declares
197 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
198 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
199 Set<String> setIntfaces = reqDecl.getInterfaces();
200 for (String strInt : setIntfaces) {
202 // Initialize a set of methods
203 Set<String> setMethods = new HashSet<String>();
204 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
205 List<String> listCapab = reqDecl.getCapabList(strInt);
206 for (String strCap : listCapab) {
208 // Get list of methods for each capability
209 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
210 List<String> listCapabMeth = capDecl.getMethods(strCap);
211 for (String strMeth : listCapabMeth) {
213 // Add methods into setMethods
214 // This is to also handle redundancies (say two capabilities
215 // share the same methods)
216 setMethods.add(strMeth);
219 // Add interface and methods information into map
220 mapNewIntMethods.put(strInt, setMethods);
221 // Map new interface method name to the original interface
222 // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
223 mapInt2NewIntName.put(origInt, strInt);
224 if (mainClass == null) // Take the first class as the main class (whichever is placed first in the order of compilation files)
227 // Map the map of interface-methods to the original interface
228 mapInt2NewInts.put(origInt, mapNewIntMethods);
237 * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
239 private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
241 for (String method : methods) {
243 List<String> methParams = intDecl.getMethodParams(method);
244 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
245 print("public " + intDecl.getMethodType(method) + " " +
246 intDecl.getMethodId(method) + "(");
247 for (int i = 0; i < methParams.size(); i++) {
248 // Check for params with driver class types and exchange it
249 // with its remote interface
250 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
251 print(paramType + " " + methParams.get(i));
252 // Check if this is the last element (don't print a comma)
253 if (i != methParams.size() - 1) {
263 * HELPER: writeMethodJavaInterface() writes the method of the interface
265 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
267 for (String method : methods) {
269 List<String> methParams = intDecl.getMethodParams(method);
270 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
271 print("public " + intDecl.getMethodType(method) + " " +
272 intDecl.getMethodId(method) + "(");
273 for (int i = 0; i < methParams.size(); i++) {
274 // Check for params with driver class types and exchange it
275 // with its remote interface
276 String paramType = methPrmTypes.get(i);
277 print(paramType + " " + methParams.get(i));
278 // Check if this is the last element (don't print a comma)
279 if (i != methParams.size() - 1) {
289 * HELPER: generateEnumJava() writes the enumeration declaration
291 private void generateEnumJava() throws IOException {
293 // Create a new directory
294 createDirectory(dir);
295 for (String intface : mapIntfacePTH.keySet()) {
296 // Get the right EnumDecl
297 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
298 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
299 Set<String> enumTypes = enumDecl.getEnumDeclarations();
300 // Iterate over enum declarations
301 for (String enType : enumTypes) {
302 // Open a new file to write into
303 FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
304 pw = new PrintWriter(new BufferedWriter(fw));
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 for (String intface : mapIntfacePTH.keySet()) {
333 // Get the right StructDecl
334 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
335 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
336 List<String> structTypes = structDecl.getStructTypes();
337 // Iterate over enum declarations
338 for (String stType : structTypes) {
339 // Open a new file to write into
340 FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
341 pw = new PrintWriter(new BufferedWriter(fw));
342 println("public class " + stType + " {");
343 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
344 List<String> structMembers = structDecl.getMembers(stType);
345 for (int i = 0; i < structMembers.size(); i++) {
347 String memberType = structMemberTypes.get(i);
348 String member = structMembers.get(i);
349 println("public static " + memberType + " " + member + ";");
353 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
360 * generateJavaLocalInterface() writes the local interface and provides type-checking.
362 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
363 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
364 * The local interface has to be the input parameter for the stub and the stub
365 * interface has to be the input parameter for the local class.
367 public void generateJavaLocalInterfaces() throws IOException {
369 // Create a new directory
370 createDirectory(dir);
371 for (String intface : mapIntfacePTH.keySet()) {
372 // Open a new file to write into
373 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
374 pw = new PrintWriter(new BufferedWriter(fw));
375 // Pass in set of methods and get import classes
376 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
377 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
378 List<String> methods = intDecl.getMethods();
379 Set<String> importClasses = getImportClasses(methods, intDecl);
380 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
381 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
382 println("package " + INTERFACE_PACKAGE + ";\n");
383 printImportStatements(allImportClasses);
384 // Write interface header
386 println("public interface " + intface + " {");
388 writeMethodJavaLocalInterface(methods, intDecl);
391 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
397 * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
399 private void updateIntfaceObjIdMap(String intface, String newIntface) {
401 // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
402 Integer objId = mapIntfaceObjId.get(intface);
403 mapNewIntfaceObjId.put(newIntface, objId);
408 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
410 public void generateJavaInterfaces() throws IOException {
412 // Create a new directory
413 String path = createDirectories(dir, subdir);
414 for (String intface : mapIntfacePTH.keySet()) {
416 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
417 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
419 // Open a new file to write into
420 String newIntface = intMeth.getKey();
421 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
422 pw = new PrintWriter(new BufferedWriter(fw));
423 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
424 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
425 // Pass in set of methods and get import classes
426 Set<String> methods = intMeth.getValue();
427 Set<String> importClasses = getImportClasses(methods, intDecl);
428 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
429 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
430 println("package " + INTERFACE_PACKAGE + ";\n");
431 printImportStatements(allImportClasses);
432 // Write interface header
434 println("public interface " + newIntface + " {\n");
435 updateIntfaceObjIdMap(intface, newIntface);
437 writeMethodJavaInterface(methods, intDecl);
440 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
447 * HELPER: writePropertiesJavaPermission() writes the permission in properties
449 private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
451 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
452 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
453 String newIntface = intMeth.getKey();
454 int newObjectId = getNewIntfaceObjectId(newIntface);
455 Set<String> methodIds = intMeth.getValue();
456 print("private static Integer[] object" + newObjectId + "Permission = { ");
458 for (String methodId : methodIds) {
459 int methodNumId = intDecl.getMethodNumId(methodId);
460 print(Integer.toString(methodNumId));
461 // Check if this is the last element (don't print a comma)
462 if (i != methodIds.size() - 1) {
468 println("private static List<Integer> set" + newObjectId + "Allowed;");
474 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
476 private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
479 Integer objId = mapIntfaceObjId.get(intface);
480 println("private int objectId = " + objId + ";");
481 println("private IoTRMIComm rmiComm;");
482 // Write the list of AtomicBoolean variables
483 println("// Synchronization variables");
484 for (String method : methods) {
485 // Generate AtomicBooleans for methods that have return values
486 String returnType = intDecl.getMethodType(method);
487 int methodNumId = intDecl.getMethodNumId(method);
488 if (!returnType.equals("void")) {
489 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
497 * HELPER: writeConstructorJavaPermission() writes the permission in constructor
499 private void writeConstructorJavaPermission(String intface) {
501 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
502 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
503 String newIntface = intMeth.getKey();
504 int newObjectId = getNewIntfaceObjectId(newIntface);
505 println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
511 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
513 private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
515 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
516 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
517 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
520 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
522 // Register the AtomicBoolean variables
523 for (String method : methods) {
524 // Generate AtomicBooleans for methods that have return values
525 String returnType = intDecl.getMethodType(method);
526 int methodNumId = intDecl.getMethodNumId(method);
527 if (!returnType.equals("void")) {
528 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
531 println("IoTRMIUtil.mapStub.put(objectId, this);");
537 * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
539 private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
541 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
542 println("rmiComm = _rmiComm;");
543 println("objectId = _objectId;");
544 // Register the AtomicBoolean variables
545 for (String method : methods) {
546 // Generate AtomicBooleans for methods that have return values
547 String returnType = intDecl.getMethodType(method);
548 int methodNumId = intDecl.getMethodNumId(method);
549 if (!returnType.equals("void")) {
550 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
558 * HELPER: getPortCount() gets port count for different stubs and skeletons
560 private int getPortCount(String intface) {
562 if (!mapPortCount.containsKey(intface))
563 mapPortCount.put(intface, portCount++);
564 return mapPortCount.get(intface);
569 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
571 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
573 // Iterate and find enum declarations
574 for (int i = 0; i < methParams.size(); i++) {
575 String paramType = methPrmTypes.get(i);
576 String param = methParams.get(i);
577 String simpleType = getGenericType(paramType);
578 if (isEnumClass(simpleType)) {
579 // Check if this is enum type
580 if (isArray(param)) { // An array
581 println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
582 println("int paramEnum" + i + "[] = new int[len" + i + "];");
583 println("for (int i = 0; i < len" + i + "; i++) {");
584 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
586 } else if (isList(paramType)) { // A list
587 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
588 println("int paramEnum" + i + "[] = new int[len" + i + "];");
589 println("for (int i = 0; i < len" + i + "; i++) {");
590 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
592 } else { // Just one element
593 println("int paramEnum" + i + "[] = new int[1];");
594 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
602 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
604 private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
606 // Write the wait-for-return-value part
607 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
608 // Strips off array "[]" for return type
609 String pureType = getSimpleArrayType(getGenericType(retType));
610 // Take the inner type of generic
611 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
612 pureType = getGenericType(retType);
613 if (isEnumClass(pureType)) {
614 // Check if this is enum type
616 println("int[] retEnum = (int[]) retObj;");
617 println(pureType + "[] enumVals = " + pureType + ".values();");
618 if (isArray(retType)) { // An array
619 println("int retLen = retEnum.length;");
620 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
621 println("for (int i = 0; i < retLen; i++) {");
622 println("enumRetVal[i] = enumVals[retEnum[i]];");
624 } else if (isList(retType)) { // A list
625 println("int retLen = retEnum.length;");
626 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
627 println("for (int i = 0; i < retLen; i++) {");
628 println("enumRetVal.add(enumVals[retEnum[i]]);");
630 } else { // Just one element
631 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
633 println("return enumRetVal;");
639 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
641 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
642 InterfaceDecl intDecl, String method) {
644 // Iterate and find struct declarations
645 for (int i = 0; i < methParams.size(); i++) {
646 String paramType = methPrmTypes.get(i);
647 String param = methParams.get(i);
648 String simpleType = getGenericType(paramType);
649 if (isStructClass(simpleType)) {
650 // Check if this is enum type
651 int methodNumId = intDecl.getMethodNumId(method);
652 String helperMethod = methodNumId + "struct" + i;
653 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
654 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
655 if (isArray(param)) { // An array
656 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
657 } else if (isList(paramType)) { // A list
658 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
659 } else { // Just one element
660 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
662 println("rmiComm.remoteCall(objectId, methodIdStruct" + i +
663 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
670 * HELPER: isStructPresent() checks presence of struct
672 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
674 // Iterate and find enum declarations
675 for (int i = 0; i < methParams.size(); i++) {
676 String paramType = methPrmTypes.get(i);
677 String param = methParams.get(i);
678 String simpleType = getGenericType(paramType);
679 if (isStructClass(simpleType))
687 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
689 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
691 // Iterate and find struct declarations - count number of params
692 for (int i = 0; i < methParams.size(); i++) {
693 String paramType = methPrmTypes.get(i);
694 String param = methParams.get(i);
695 String simpleType = getGenericType(paramType);
696 if (isStructClass(simpleType)) {
697 int members = getNumOfMembers(simpleType);
698 if (isArray(param)) { // An array
699 String structLen = getSimpleArrayType(param) + ".length";
700 print(members + "*" + structLen);
701 } else if (isList(paramType)) { // A list
702 String structLen = getSimpleArrayType(param) + ".size()";
703 print(members + "*" + structLen);
705 print(Integer.toString(members));
708 if (i != methParams.size() - 1) {
716 * HELPER: writeStructMembersJavaStub() writes parameters of struct
718 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
720 // Get the struct declaration for this struct and generate initialization code
721 StructDecl structDecl = getStructDecl(simpleType);
722 List<String> memTypes = structDecl.getMemberTypes(simpleType);
723 List<String> members = structDecl.getMembers(simpleType);
724 if (isArray(param)) { // An array
725 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
726 for (int i = 0; i < members.size(); i++) {
727 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
728 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
729 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
730 print(getSimpleIdentifier(members.get(i)));
734 } else if (isList(paramType)) { // A list
735 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
736 for (int i = 0; i < members.size(); i++) {
737 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
738 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
739 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
740 print(getSimpleIdentifier(members.get(i)));
744 } else { // Just one struct element
745 for (int i = 0; i < members.size(); i++) {
746 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
747 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
748 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
749 print(getSimpleIdentifier(members.get(i)));
757 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
759 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
761 print("int paramLen = ");
762 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
764 println("Object[] paramObj = new Object[paramLen];");
765 println("Class<?>[] paramCls = new Class<?>[paramLen];");
766 println("int pos = 0;");
767 // Iterate again over the parameters
768 for (int i = 0; i < methParams.size(); i++) {
769 String paramType = methPrmTypes.get(i);
770 String param = methParams.get(i);
771 String simpleType = getGenericType(paramType);
772 if (isStructClass(simpleType)) {
773 writeStructMembersJavaStub(simpleType, paramType, param);
774 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
775 println("paramCls[pos] = int[].class;");
776 println("paramObj[pos++] = objIdSent" + i + ";");
778 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
779 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
780 print("paramObj[pos++] = ");
781 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
790 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
792 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
794 // Get the struct declaration for this struct and generate initialization code
795 StructDecl structDecl = getStructDecl(simpleType);
796 List<String> memTypes = structDecl.getMemberTypes(simpleType);
797 List<String> members = structDecl.getMembers(simpleType);
798 if (isArrayOrList(retType, retType)) { // An array or list
799 println("for(int i = 0; i < retLen; i++) {");
801 if (isArray(retType)) { // An array
802 for (int i = 0; i < members.size(); i++) {
803 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
804 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
805 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
808 } else if (isList(retType)) { // A list
809 println(simpleType + " structRetMem = new " + simpleType + "();");
810 for (int i = 0; i < members.size(); i++) {
811 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
812 print("structRetMem." + getSimpleIdentifier(members.get(i)));
813 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
815 println("structRet.add(structRetMem);");
817 } else { // Just one struct element
818 for (int i = 0; i < members.size(); i++) {
819 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
820 print("structRet." + getSimpleIdentifier(members.get(i)));
821 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
824 println("return structRet;");
829 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
831 private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
833 // Handle the returned struct size
834 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
835 // Minimum retLen is 1 if this is a single struct object
836 println("int retLen = (int) retObj;");
837 int numMem = getNumOfMembers(simpleType);
838 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
839 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
840 println("int retPos = 0;");
841 // Get the struct declaration for this struct and generate initialization code
842 StructDecl structDecl = getStructDecl(simpleType);
843 List<String> memTypes = structDecl.getMemberTypes(simpleType);
844 List<String> members = structDecl.getMembers(simpleType);
845 if (isArrayOrList(retType, retType)) { // An array or list
846 println("for(int i = 0; i < retLen; i++) {");
847 for (int i = 0; i < members.size(); i++) {
848 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
849 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
850 println("retClsVal[retPos++] = null;");
853 } else { // Just one struct element
854 for (int i = 0; i < members.size(); i++) {
855 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
856 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
857 println("retClsVal[retPos++] = null;");
860 // Handle the actual returned struct
861 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
862 if (isArray(retType)) { // An array
863 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
864 println("for(int i = 0; i < retLen; i++) {");
865 println("structRet[i] = new " + simpleType + "();");
867 } else if (isList(retType)) { // A list
868 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
870 println(simpleType + " structRet = new " + simpleType + "();");
871 println("int retObjPos = 0;");
872 writeStructRetMembersJavaStub(simpleType, retType);
877 * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
879 private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
881 println("// Waiting for return value");
882 int methodNumId = intDecl.getMethodNumId(method);
883 println("while (!retValueReceived" + methodNumId + ".get());");
884 println(getReturnValue);
885 println("retValueReceived" + methodNumId + ".set(false);");
886 println("rmiComm.setGetReturnBytes();\n");
891 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
893 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
894 List<String> methPrmTypes, String method, Set<String> callbackType) {
896 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
897 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
898 String retType = intDecl.getMethodType(method);
899 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
900 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
901 // Generate array of parameter types
902 if (isStructPresent(methParams, methPrmTypes)) {
903 writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
905 print("Class<?>[] paramCls = new Class<?>[] { ");
906 for (int i = 0; i < methParams.size(); i++) {
907 String prmType = methPrmTypes.get(i);
908 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
909 print("int[].class");
910 } else { // Generate normal classes if it's not a callback object
911 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
912 print(getSimpleType(getEnumType(paramType)) + ".class");
914 // Check if this is the last element (don't print a comma)
915 if (i != methParams.size() - 1) {
920 // Generate array of parameter objects
921 print("Object[] paramObj = new Object[] { ");
922 for (int i = 0; i < methParams.size(); i++) {
923 String paramType = methPrmTypes.get(i);
924 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
925 print("objIdSent" + i);
927 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
928 // Check if this is the last element (don't print a comma)
929 if (i != methParams.size() - 1) {
935 // Send method call first and wait for return value separately
936 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
937 // Check if this is "void"
938 if (!retType.equals("void")) { // We do have a return value
939 // Generate array of parameter types
940 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
941 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
943 // This is an enum type
944 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
945 //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
946 checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
947 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
948 // Check if the return value NONPRIMITIVES
949 String retGenValType = getGenericType(retType);
950 println("Class<?> retGenValType = " + retGenValType + ".class;");
951 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
952 println("return (" + retType + ")retObj;");
954 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
955 println("return (" + retType + ")retObj;");
963 * HELPER: returnGenericCallbackType() returns the callback type
965 private String returnGenericCallbackType(String paramType) {
967 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
968 return getGenericType(paramType);
975 * HELPER: checkCallbackType() checks the callback type
977 private boolean checkCallbackType(String paramType, Set<String> callbackType) {
979 String prmType = returnGenericCallbackType(paramType);
980 if (callbackType == null) // If there is no callbackType it means not a callback method
983 for (String type : callbackType) {
984 if (type.equals(prmType))
985 return true; // Check callbackType one by one
993 * HELPER: checkCallbackType() checks the callback type
995 private boolean checkCallbackType(String paramType, String callbackType) {
997 String prmType = returnGenericCallbackType(paramType);
998 if (callbackType == null) // If there is no callbackType it means not a callback method
1001 return callbackType.equals(prmType);
1006 * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1008 private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1010 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1011 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1012 if (isMultipleCallbacks)
1013 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1015 println("objIdSent" + counter + "[0] = newObjIdSent;");
1016 println("rmiComm.decrementObjectIdCounter();");
1017 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1018 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1019 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1020 println("Thread thread = new Thread() {");
1021 println("public void run() {");
1023 println("skel" + counter + ".___waitRequestInvokeMethod();");
1024 println("} catch (Exception ex) {");
1025 println("ex.printStackTrace();");
1026 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " +
1027 callbackType + "_Skeleton!\");");
1031 println("thread.start();");
1032 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1036 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1037 if (isMultipleCallbacks)
1038 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1040 println("objIdSent" + counter + "[0] = newObjIdSent;");
1046 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1048 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1049 List<String> methPrmTypes, String method, Set<String> callbackType) {
1051 // Determine callback object counter type (List vs. single variable)
1052 for (int i = 0; i < methParams.size(); i++) {
1053 String paramType = methPrmTypes.get(i);
1054 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1055 print("int[] objIdSent" + i + " = ");
1056 String param = methParams.get(i);
1057 if (isArray(methParams.get(i)))
1058 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1059 else if (isList(methPrmTypes.get(i)))
1060 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1062 println("new int[1];");
1066 // Check if this is single object, array, or list of objects
1067 for (int i = 0; i < methParams.size(); i++) {
1068 String paramType = methPrmTypes.get(i);
1069 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1070 String param = methParams.get(i);
1071 if (isArrayOrList(paramType, param)) { // Generate loop
1072 println("int cnt" + i + " = 0;");
1073 println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1074 writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1076 writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1077 if (isArrayOrList(paramType, param))
1082 println(" catch (Exception ex) {");
1083 println("ex.printStackTrace();");
1084 println("throw new Error(\"Exception when generating skeleton objects!\");");
1090 * HELPER: writeMethodJavaStub() writes the methods of the stub class
1092 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1094 for (String method : methods) {
1096 List<String> methParams = intDecl.getMethodParams(method);
1097 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1098 print("public " + intDecl.getMethodType(method) + " " +
1099 intDecl.getMethodId(method) + "(");
1100 boolean isCallbackMethod = false;
1101 //String callbackType = null;
1102 Set<String> callbackType = new HashSet<String>();
1103 for (int i = 0; i < methParams.size(); i++) {
1105 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1106 // Check if this has callback object
1107 if (callbackClasses.contains(paramType)) {
1108 isCallbackMethod = true;
1109 //callbackType = paramType;
1110 callbackType.add(paramType);
1111 // Even if there're 2 callback arguments, we expect them to be of the same interface
1113 print(methPrmTypes.get(i) + " " + methParams.get(i));
1114 // Check if this is the last element (don't print a comma)
1115 if (i != methParams.size() - 1) {
1120 // Now, write the body of stub!
1121 if (isCallbackMethod)
1122 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1123 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1130 * HELPER: getStubInterface() gets stub interface name based on original interface
1132 public String getStubInterface(String intface) {
1134 return mapInt2NewIntName.get(intface);
1139 * generateJavaStubClasses() generate stubs based on the methods list in Java
1141 public void generateJavaStubClasses() throws IOException {
1143 // Create a new directory
1144 String path = createDirectories(dir, subdir);
1145 for (String intface : mapIntfacePTH.keySet()) {
1147 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1148 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1150 // Open a new file to write into
1151 String newIntface = intMeth.getKey();
1152 String newStubClass = newIntface + "_Stub";
1153 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1154 pw = new PrintWriter(new BufferedWriter(fw));
1155 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1156 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1157 // Pass in set of methods and get import classes
1158 Set<String> methods = intMeth.getValue();
1159 Set<String> importClasses = getImportClasses(methods, intDecl);
1160 List<String> stdImportClasses = getStandardJavaImportClasses();
1161 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1162 // Find out if there are callback objects
1163 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1164 boolean callbackExist = !callbackClasses.isEmpty();
1165 // Check if this interface is a callback class
1166 if(isCallbackClass(intface))
1167 println("package " + CODE_PREFIX + "." + mapInt2Drv.get(intface) + ";\n");
1169 println("package " + controllerClass + ";\n");
1170 printImportStatements(allImportClasses);
1171 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
1172 // Write class header
1173 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1175 writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1176 // Write constructor
1177 writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1178 // Write callback constructor (used if this stub is treated as a callback stub)
1179 writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1181 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1184 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1191 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1193 private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1195 println("private " + intface + " mainObj;");
1196 Integer objId = mapIntfaceObjId.get(intface);
1197 println("private int objectId = " + objId + ";");
1198 println("// Communications and synchronizations");
1199 println("private IoTRMIComm rmiComm;");
1200 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1201 println("private AtomicBoolean methodReceived;");
1202 println("private byte[] methodBytes = null;");
1203 println("// Permissions");
1204 writePropertiesJavaPermission(intface, intDecl);
1210 * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1212 private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1214 // Use this set to handle two same methodIds
1215 for (String method : methods) {
1216 List<String> methParams = intDecl.getMethodParams(method);
1217 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1218 // Check for params with structs
1219 for (int i = 0; i < methParams.size(); i++) {
1220 String paramType = methPrmTypes.get(i);
1221 String param = methParams.get(i);
1222 String simpleType = getGenericType(paramType);
1223 if (isStructClass(simpleType)) {
1224 int methodNumId = intDecl.getMethodNumId(method);
1225 String helperMethod = methodNumId + "struct" + i;
1226 int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1227 // Iterate over interfaces to give permissions to
1228 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1229 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1230 String newIntface = intMeth.getKey();
1231 int newObjectId = getNewIntfaceObjectId(newIntface);
1232 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1241 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1243 private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1244 Collection<String> methods, boolean callbackExist) {
1246 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1247 println("mainObj = _mainObj;");
1248 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1249 // Generate permission control initialization
1250 writeConstructorJavaPermission(intface);
1251 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1252 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1253 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1254 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1255 println("methodReceived = new AtomicBoolean(false);");
1256 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1257 println("Thread thread1 = new Thread() {");
1258 println("public void run() {");
1260 println("___waitRequestInvokeMethod();");
1262 println("catch (Exception ex)");
1264 println("ex.printStackTrace();");
1268 println("thread1.start();");
1274 * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1276 private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1277 Collection<String> methods, boolean callbackExist) {
1279 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1280 println("mainObj = _mainObj;");
1281 println("rmiComm = _rmiComm;");
1282 println("objectId = _objectId;");
1283 // Generate permission control initialization
1284 writeConstructorJavaPermission(intface);
1285 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1286 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1287 println("methodReceived = new AtomicBoolean(false);");
1288 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1294 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1296 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1298 if (methodType.equals("void"))
1299 print("mainObj." + methodId + "(");
1301 print("return mainObj." + methodId + "(");
1302 for (int i = 0; i < methParams.size(); i++) {
1304 print(getSimpleIdentifier(methParams.get(i)));
1305 // Check if this is the last element (don't print a comma)
1306 if (i != methParams.size() - 1) {
1315 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1317 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1319 for (String method : methods) {
1321 List<String> methParams = intDecl.getMethodParams(method);
1322 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1323 String methodId = intDecl.getMethodId(method);
1324 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1325 for (int i = 0; i < methParams.size(); i++) {
1327 String origParamType = methPrmTypes.get(i);
1328 String paramType = checkAndGetParamClass(origParamType);
1329 print(paramType + " " + methParams.get(i));
1330 // Check if this is the last element (don't print a comma)
1331 if (i != methParams.size() - 1) {
1336 // Now, write the body of skeleton!
1337 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1344 * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1346 private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1348 println(exchParamType + " newStub" + counter + " = null;");
1349 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1350 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1351 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1352 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1353 println("rmiComm.decrementObjectIdCounter();");
1356 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1362 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1364 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1365 Set<String> callbackType, boolean isStructMethod) {
1367 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1368 String offsetPfx = "";
1370 offsetPfx = "offset";
1371 // Iterate over callback objects
1372 for (int i = 0; i < methParams.size(); i++) {
1373 String paramType = methPrmTypes.get(i);
1374 String param = methParams.get(i);
1375 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1376 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1377 // Print array if this is array or list if this is a list of callback objects
1378 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1379 if (isArray(param)) {
1380 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1381 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1382 } else if (isList(paramType)) {
1383 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1384 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1386 println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1387 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1390 // Generate a loop if needed
1391 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1392 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1393 if (isArray(param)) {
1394 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1395 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1396 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1397 println("stub" + i + "[i] = newStub" + i + ";");
1399 } else if (isList(paramType)) {
1400 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1401 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1402 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1403 println("stub" + i + ".add(newStub" + i + ");");
1406 println(exchParamType + " stub" + i + " = newStub" + i + ";");
1407 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1410 return mapStubParam;
1415 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1417 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1419 String offsetPfx = "";
1421 offsetPfx = "offset";
1422 // Iterate and find enum declarations
1423 boolean printed = false;
1424 for (int i = 0; i < methParams.size(); i++) {
1425 String paramType = methPrmTypes.get(i);
1426 String param = methParams.get(i);
1427 String simpleType = getGenericType(paramType);
1428 if (isEnumClass(simpleType)) {
1429 // Check if this is enum type
1430 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1432 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1435 if (isArray(param)) { // An array
1436 println("int len" + i + " = paramInt" + i + ".length;");
1437 println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1438 println("for (int i = 0; i < len" + i + "; i++) {");
1439 println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1441 } else if (isList(paramType)) { // A list
1442 println("int len" + i + " = paramInt" + i + ".length;");
1443 println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1444 println("for (int i = 0; i < len" + i + "; i++) {");
1445 println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1447 } else { // Just one element
1448 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1456 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1458 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1460 // Strips off array "[]" for return type
1461 String pureType = getSimpleArrayType(getGenericType(retType));
1462 // Take the inner type of generic
1463 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1464 pureType = getGenericType(retType);
1465 if (isEnumClass(pureType)) {
1466 // Check if this is enum type
1468 if (isArray(retType)) { // An array
1469 print(pureType + "[] retEnum = " + methodId + "(");
1470 } else if (isList(retType)) { // A list
1471 print("List<" + pureType + "> retEnum = " + methodId + "(");
1472 } else { // Just one element
1473 print(pureType + " retEnum = " + methodId + "(");
1480 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1482 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1484 // Strips off array "[]" for return type
1485 String pureType = getSimpleArrayType(getGenericType(retType));
1486 // Take the inner type of generic
1487 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1488 pureType = getGenericType(retType);
1489 if (isEnumClass(pureType)) {
1490 // Check if this is enum type
1491 if (isArray(retType)) { // An array
1492 println("int retLen = retEnum.length;");
1493 println("int[] retEnumVal = new int[retLen];");
1494 println("for (int i = 0; i < retLen; i++) {");
1495 println("retEnumVal[i] = retEnum[i].ordinal();");
1497 } else if (isList(retType)) { // A list
1498 println("int retLen = retEnum.size();");
1499 println("int[] retEnumVal = new int[retLen];");
1500 println("for (int i = 0; i < retLen; i++) {");
1501 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1503 } else { // Just one element
1504 println("int[] retEnumVal = new int[1];");
1505 println("retEnumVal[0] = retEnum.ordinal();");
1507 println("Object retObj = retEnumVal;");
1513 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1515 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1516 String method, InterfaceDecl intDecl) {
1518 // Iterate and find struct declarations - count number of params
1519 for (int i = 0; i < methParams.size(); i++) {
1520 String paramType = methPrmTypes.get(i);
1521 String param = methParams.get(i);
1522 String simpleType = getGenericType(paramType);
1523 if (isStructClass(simpleType)) {
1524 int members = getNumOfMembers(simpleType);
1525 print(Integer.toString(members) + "*");
1526 int methodNumId = intDecl.getMethodNumId(method);
1527 print("struct" + methodNumId + "Size" + i);
1530 if (i != methParams.size() - 1) {
1538 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1540 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1541 String param, String method, InterfaceDecl intDecl, int iVar) {
1543 // Get the struct declaration for this struct and generate initialization code
1544 StructDecl structDecl = getStructDecl(simpleType);
1545 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1546 List<String> members = structDecl.getMembers(simpleType);
1547 if (isArrayOrList(paramType, param)) { // An array or list
1548 int methodNumId = intDecl.getMethodNumId(method);
1549 String counter = "struct" + methodNumId + "Size" + iVar;
1550 println("for(int i = 0; i < " + counter + "; i++) {");
1552 if (isArrayOrList(paramType, param)) { // An array or list
1553 for (int i = 0; i < members.size(); i++) {
1554 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1555 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1556 println("paramClsGen[pos++] = null;");
1559 } else { // Just one struct element
1560 for (int i = 0; i < members.size(); i++) {
1561 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1562 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1563 println("paramClsGen[pos++] = null;");
1570 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1572 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1573 List<String> methPrmTypes, String method) {
1575 println("int objPos = 0;");
1576 for (int i = 0; i < methParams.size(); i++) {
1577 String paramType = methPrmTypes.get(i);
1578 String param = methParams.get(i);
1579 String simpleType = getGenericType(paramType);
1580 if (isStructClass(simpleType)) {
1581 int methodNumId = intDecl.getMethodNumId(method);
1582 String counter = "struct" + methodNumId + "Size" + i;
1584 if (isArray(param)) { // An array
1585 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1586 println("for(int i = 0; i < " + counter + "; i++) {");
1587 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1589 } else if (isList(paramType)) { // A list
1590 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1592 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1593 // Initialize members
1594 StructDecl structDecl = getStructDecl(simpleType);
1595 List<String> members = structDecl.getMembers(simpleType);
1596 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1597 if (isArrayOrList(paramType, param)) { // An array or list
1598 println("for(int i = 0; i < " + counter + "; i++) {");
1600 if (isArray(param)) { // An array
1601 for (int j = 0; j < members.size(); j++) {
1602 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1603 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1604 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1607 } else if (isList(paramType)) { // A list
1608 println(simpleType + " paramStructMem = new " + simpleType + "();");
1609 for (int j = 0; j < members.size(); j++) {
1610 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1611 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1612 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1614 println("paramStruct" + i + ".add(paramStructMem);");
1616 } else { // Just one struct element
1617 for (int j = 0; j < members.size(); j++) {
1618 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1619 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1620 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1624 // Take offsets of parameters
1625 println("int offset" + i +" = objPos++;");
1632 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1634 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1636 // Minimum retLen is 1 if this is a single struct object
1637 if (isArray(retType))
1638 println("int retLen = retStruct.length;");
1639 else if (isList(retType))
1640 println("int retLen = retStruct.size();");
1641 else // Just single struct object
1642 println("int retLen = 1;");
1643 println("Object retLenObj = retLen;");
1644 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1645 int numMem = getNumOfMembers(simpleType);
1646 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1647 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1648 println("int retPos = 0;");
1649 // Get the struct declaration for this struct and generate initialization code
1650 StructDecl structDecl = getStructDecl(simpleType);
1651 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1652 List<String> members = structDecl.getMembers(simpleType);
1653 if (isArray(retType)) { // An array or list
1654 println("for(int i = 0; i < retLen; i++) {");
1655 for (int i = 0; i < members.size(); i++) {
1656 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1657 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1658 print("retObj[retPos++] = retStruct[i].");
1659 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1663 } else if (isList(retType)) { // An array or list
1664 println("for(int i = 0; i < retLen; i++) {");
1665 for (int i = 0; i < members.size(); i++) {
1666 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1667 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1668 print("retObj[retPos++] = retStruct.get(i).");
1669 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1673 } else { // Just one struct element
1674 for (int i = 0; i < members.size(); i++) {
1675 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1676 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1677 print("retObj[retPos++] = retStruct.");
1678 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1687 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1689 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1690 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1691 boolean isStructMethod) {
1693 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1694 Map<Integer,String> mapStubParam = null;
1695 if (isCallbackMethod) {
1697 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1699 // Check if this is "void"
1700 String retType = intDecl.getMethodType(method);
1701 if (retType.equals("void")) {
1702 print(intDecl.getMethodId(method) + "(");
1703 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1704 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1705 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1706 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1707 } else { // We do have a return value
1708 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1710 for (int i = 0; i < methParams.size(); i++) {
1712 String paramType = methPrmTypes.get(i);
1713 if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1714 print(mapStubParam.get(i)); // Get the callback parameter
1715 } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1716 print(getEnumParam(paramType, methParams.get(i), i));
1717 } else if (isStructClass(getGenericType(paramType))) {
1718 print("paramStruct" + i);
1720 String prmType = checkAndGetArray(paramType, methParams.get(i));
1722 print("(" + prmType + ") paramObj[offset" + i + "]");
1724 print("(" + prmType + ") paramObj[" + i + "]");
1726 if (i != methParams.size() - 1)
1730 if (!retType.equals("void")) {
1731 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1732 checkAndWriteEnumRetConvJavaSkeleton(retType);
1733 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1734 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1735 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1736 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1738 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1740 if (isCallbackMethod) { // Catch exception if this is callback
1742 println(" catch(Exception ex) {");
1743 println("ex.printStackTrace();");
1744 println("throw new Error(\"Exception from callback object instantiation!\");");
1751 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1753 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1754 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1756 // Generate array of parameter objects
1757 boolean isCallbackMethod = false;
1758 Set<String> callbackType = new HashSet<String>();
1759 println("byte[] localMethodBytes = methodBytes;");
1760 println("rmiComm.setGetMethodBytes();");
1761 print("int paramLen = ");
1762 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1764 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1765 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1766 println("int pos = 0;");
1767 // Iterate again over the parameters
1768 for (int i = 0; i < methParams.size(); i++) {
1769 String paramType = methPrmTypes.get(i);
1770 String param = methParams.get(i);
1771 String simpleType = getGenericType(paramType);
1772 if (isStructClass(simpleType)) {
1773 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1775 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1776 if (callbackClasses.contains(prmType)) {
1777 isCallbackMethod = true;
1778 //callbackType = prmType;
1779 callbackType.add(prmType);
1780 println("paramCls[pos] = int[].class;");
1781 println("paramClsGen[pos++] = null;");
1782 } else { // Generate normal classes if it's not a callback object
1783 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1784 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1785 print("paramClsGen[pos++] = ");
1786 String prmTypeOth = methPrmTypes.get(i);
1787 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1788 println(getTypeOfGeneric(prmType)[0] + ".class;");
1794 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1795 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1796 // Write the return value part
1797 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1802 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1804 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1805 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1807 // Generate array of parameter objects
1808 boolean isCallbackMethod = false;
1809 Set<String> callbackType = new HashSet<String>();
1810 println("byte[] localMethodBytes = methodBytes;");
1811 println("rmiComm.setGetMethodBytes();");
1812 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1813 for (int i = 0; i < methParams.size(); i++) {
1815 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1816 if (callbackClasses.contains(paramType)) {
1817 isCallbackMethod = true;
1818 callbackType.add(paramType);
1819 print("int[].class");
1820 } else { // Generate normal classes if it's not a callback object
1821 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1822 print(getSimpleType(getEnumType(prmType)) + ".class");
1824 if (i != methParams.size() - 1)
1827 // Generate generic class if it's a generic type.. null otherwise
1828 print(" }, new Class<?>[] { ");
1829 for (int i = 0; i < methParams.size(); i++) {
1830 String prmType = methPrmTypes.get(i);
1831 if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1832 !isEnumClass(getGenericType(prmType)) &&
1833 !callbackClasses.contains(getGenericType(prmType)))
1834 print(getGenericType(prmType) + ".class");
1837 if (i != methParams.size() - 1)
1840 println(" }, localMethodBytes);");
1841 // Write the return value part
1842 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1847 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1849 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1851 // Use this set to handle two same methodIds
1852 Set<String> uniqueMethodIds = new HashSet<String>();
1853 for (String method : methods) {
1855 List<String> methParams = intDecl.getMethodParams(method);
1856 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1857 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1858 String methodId = intDecl.getMethodId(method);
1859 print("public void ___");
1860 String helperMethod = methodId;
1861 if (uniqueMethodIds.contains(methodId))
1862 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1864 uniqueMethodIds.add(methodId);
1865 String retType = intDecl.getMethodType(method);
1866 print(helperMethod + "(");
1867 boolean begin = true;
1868 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1869 String paramType = methPrmTypes.get(i);
1870 String param = methParams.get(i);
1871 String simpleType = getGenericType(paramType);
1872 if (isStructClass(simpleType)) {
1873 if (!begin) // Generate comma for not the beginning variable
1877 int methodNumId = intDecl.getMethodNumId(method);
1878 print("int struct" + methodNumId + "Size" + i);
1881 // Check if this is "void"
1882 if (retType.equals("void"))
1885 println(") throws IOException {");
1886 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1889 String methodId = intDecl.getMethodId(method);
1890 print("public void ___");
1891 String helperMethod = methodId;
1892 if (uniqueMethodIds.contains(methodId))
1893 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1895 uniqueMethodIds.add(methodId);
1896 // Check if this is "void"
1897 String retType = intDecl.getMethodType(method);
1898 if (retType.equals("void"))
1899 println(helperMethod + "() {");
1901 println(helperMethod + "() throws IOException {");
1902 // Now, write the helper body of skeleton!
1903 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1907 // Write method helper for structs
1908 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1913 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1915 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1916 InterfaceDecl intDecl) {
1918 // Use this set to handle two same methodIds
1919 for (String method : methods) {
1921 List<String> methParams = intDecl.getMethodParams(method);
1922 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1923 // Check for params with structs
1924 for (int i = 0; i < methParams.size(); i++) {
1925 String paramType = methPrmTypes.get(i);
1926 String param = methParams.get(i);
1927 String simpleType = getGenericType(paramType);
1928 if (isStructClass(simpleType)) {
1929 int methodNumId = intDecl.getMethodNumId(method);
1930 print("public int ___");
1931 String helperMethod = methodNumId + "struct" + i;
1932 println(helperMethod + "() {");
1933 // Now, write the helper body of skeleton!
1934 println("byte[] localMethodBytes = methodBytes;");
1935 println("rmiComm.setGetMethodBytes();");
1936 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1937 println("return (int) paramObj[0];");
1946 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1948 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1949 InterfaceDecl intDecl) {
1951 // Use this set to handle two same methodIds
1952 for (String method : methods) {
1954 List<String> methParams = intDecl.getMethodParams(method);
1955 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1956 // Check for params with structs
1957 for (int i = 0; i < methParams.size(); i++) {
1958 String paramType = methPrmTypes.get(i);
1959 String param = methParams.get(i);
1960 String simpleType = getGenericType(paramType);
1961 if (isStructClass(simpleType)) {
1962 int methodNumId = intDecl.getMethodNumId(method);
1963 print("public int ___");
1964 String helperMethod = methodNumId + "struct" + i;
1965 println(helperMethod + "(IoTRMIObject rmiObj) {");
1966 // Now, write the helper body of skeleton!
1967 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1968 println("return (int) paramObj[0];");
1977 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1979 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1981 // Use this set to handle two same methodIds
1982 for (String method : methods) {
1984 List<String> methParams = intDecl.getMethodParams(method);
1985 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1986 // Check for params with structs
1987 for (int i = 0; i < methParams.size(); i++) {
1988 String paramType = methPrmTypes.get(i);
1989 String param = methParams.get(i);
1990 String simpleType = getGenericType(paramType);
1991 if (isStructClass(simpleType)) {
1992 int methodNumId = intDecl.getMethodNumId(method);
1993 println("int struct" + methodNumId + "Size" + i + " = 0;");
2001 * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
2003 private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
2005 List<String> methParams = intDecl.getMethodParams(method);
2006 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2007 boolean structExist = false;
2008 boolean begin = true;
2009 // Check for params with structs
2010 for (int i = 0; i < methParams.size(); i++) {
2011 String paramType = methPrmTypes.get(i);
2012 String param = methParams.get(i);
2013 String simpleType = getGenericType(paramType);
2014 if (isStructClass(simpleType)) {
2020 int methodNumId = intDecl.getMethodNumId(method);
2021 print("struct" + methodNumId + "Size" + i + "Final");
2029 * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2031 private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2033 List<String> methParams = intDecl.getMethodParams(method);
2034 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2035 boolean structExist = false;
2036 boolean begin = true;
2037 // Check for params with structs
2038 for (int i = 0; i < methParams.size(); i++) {
2039 String paramType = methPrmTypes.get(i);
2040 String param = methParams.get(i);
2041 String simpleType = getGenericType(paramType);
2042 if (isStructClass(simpleType)) {
2048 int methodNumId = intDecl.getMethodNumId(method);
2049 print("struct" + methodNumId + "Size" + i);
2057 * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2059 private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2061 // Use this set to handle two same methodIds
2062 for (String method : methods) {
2064 List<String> methParams = intDecl.getMethodParams(method);
2065 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2066 // Check for params with structs
2067 for (int i = 0; i < methParams.size(); i++) {
2068 String paramType = methPrmTypes.get(i);
2069 String param = methParams.get(i);
2070 String simpleType = getGenericType(paramType);
2071 if (isStructClass(simpleType)) {
2072 int methodNumId = intDecl.getMethodNumId(method);
2074 String helperMethod = methodNumId + "struct" + i;
2075 String tempVar = "struct" + methodNumId + "Size" + i;
2076 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2077 print(tempVar + " = ___");
2078 println(helperMethod + "(); break;");
2086 * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2088 private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2090 // Use this set to handle two same methodIds
2091 for (String method : methods) {
2093 List<String> methParams = intDecl.getMethodParams(method);
2094 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2095 // Check for params with structs
2096 for (int i = 0; i < methParams.size(); i++) {
2097 String paramType = methPrmTypes.get(i);
2098 String param = methParams.get(i);
2099 String simpleType = getGenericType(paramType);
2100 if (isStructClass(simpleType)) {
2101 int methodNumId = intDecl.getMethodNumId(method);
2103 String helperMethod = methodNumId + "struct" + i;
2104 String tempVar = "struct" + methodNumId + "Size" + i;
2105 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2106 print(tempVar + " = ___");
2107 println(helperMethod + "(skel); break;");
2115 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2117 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2119 // Use this set to handle two same methodIds
2120 for (String method : methods) {
2122 List<String> methParams = intDecl.getMethodParams(method);
2123 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2124 // Check for params with structs
2125 for (int i = 0; i < methParams.size(); i++) {
2126 String paramType = methPrmTypes.get(i);
2127 String param = methParams.get(i);
2128 String simpleType = getGenericType(paramType);
2129 if (isStructClass(simpleType)) {
2130 int methodNumId = intDecl.getMethodNumId(method);
2132 String helperMethod = methodNumId + "struct" + i;
2133 String tempVar = "struct" + methodNumId + "Size" + i;
2134 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2135 print(tempVar + " = ___");
2136 println(helperMethod + "(rmiObj); break;");
2144 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2146 private void writeJavaMethodPermission(String intface) {
2148 // Get all the different stubs
2149 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2150 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2151 String newIntface = intMeth.getKey();
2152 int newObjectId = getNewIntfaceObjectId(newIntface);
2153 println("if (_objectId == objectId) {");
2154 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2155 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
2159 println("continue;");
2166 * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2168 private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2170 List<String> methParams = intDecl.getMethodParams(method);
2171 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2172 boolean structExist = false;
2173 boolean begin = true;
2174 // Check for params with structs
2175 for (int i = 0; i < methParams.size(); i++) {
2176 String paramType = methPrmTypes.get(i);
2177 String param = methParams.get(i);
2178 String simpleType = getGenericType(paramType);
2179 if (isStructClass(simpleType)) {
2181 int methodNumId = intDecl.getMethodNumId(method);
2182 println("final int struct" + methodNumId + "Size" + i +
2183 "Final = struct" + methodNumId + "Size" + i + ";");
2191 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2193 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2195 // Use this set to handle two same methodIds
2196 Set<String> uniqueMethodIds = new HashSet<String>();
2197 println("public void ___waitRequestInvokeMethod() throws IOException {");
2198 // Write variables here if we have callbacks or enums or structs
2199 writeCountVarStructSkeleton(methods, intDecl);
2200 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2201 println("while (true) {");
2202 println("if (!methodReceived.get()) {");
2203 println("continue;");
2205 println("methodBytes = rmiComm.getMethodBytes();");
2206 println("methodReceived.set(false);");
2207 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2208 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2209 // Generate permission check
2210 writeJavaMethodPermission(intface);
2211 println("switch (methodId) {");
2212 // Print methods and method Ids
2213 for (String method : methods) {
2214 String methodId = intDecl.getMethodId(method);
2215 int methodNumId = intDecl.getMethodNumId(method);
2216 println("case " + methodNumId + ":");
2217 // Check for stuct counters
2218 writeFinalInputCountVarStructSkeleton(method, intDecl);
2219 println("new Thread() {");
2220 println("public void run() {");
2223 String helperMethod = methodId;
2224 if (uniqueMethodIds.contains(methodId))
2225 helperMethod = helperMethod + methodNumId;
2227 uniqueMethodIds.add(methodId);
2228 print(helperMethod + "(");
2229 writeInputCountVarStructJavaSkeleton(method, intDecl);
2232 println("catch (Exception ex) {");
2233 println("ex.printStackTrace();");
2236 println("}.start();");
2239 String method = "___initCallBack()";
2240 writeMethodCallStructJavaSkeleton(methods, intDecl);
2241 println("default: ");
2242 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2250 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2252 private void writeReturnDidAlreadyInitWaitInvoke() {
2254 println("public boolean didAlreadyInitWaitInvoke() {");
2255 println("return didAlreadyInitWaitInvoke.get();");
2261 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2263 public void generateJavaSkeletonClass() throws IOException {
2265 // Create a new directory
2266 String path = createDirectories(dir, subdir);
2267 for (String intface : mapIntfacePTH.keySet()) {
2268 // Open a new file to write into
2269 String newSkelClass = intface + "_Skeleton";
2270 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2271 pw = new PrintWriter(new BufferedWriter(fw));
2272 // Pass in set of methods and get import classes
2273 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2274 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2275 List<String> methods = intDecl.getMethods();
2276 Set<String> importClasses = getImportClasses(methods, intDecl);
2277 List<String> stdImportClasses = getStandardJavaImportClasses();
2278 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2279 // Find out if there are callback objects
2280 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2281 boolean callbackExist = !callbackClasses.isEmpty();
2282 if(isCallbackClass(intface))
2283 println("package " + controllerClass + ";\n");
2285 println("package " + CODE_PREFIX + "." + mapInt2Drv.get(intface) + ";\n");
2286 printImportStatements(allImportClasses);
2287 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
2288 // Write class header
2289 println("public class " + newSkelClass + " implements " + intface + " {\n");
2291 writePropertiesJavaSkeleton(intface, intDecl);
2292 // Write constructor
2293 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2294 // Write constructor that is called when this object is a callback object
2295 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2296 // Write function to return didAlreadyInitWaitInvoke
2297 writeReturnDidAlreadyInitWaitInvoke();
2299 writeMethodJavaSkeleton(methods, intDecl);
2300 // Write method helper
2301 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2302 // Write waitRequestInvokeMethod() - main loop
2303 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2306 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2311 /*================================================================================
2315 *================================================================================/
2318 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2320 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2322 for (String method : methods) {
2324 List<String> methParams = intDecl.getMethodParams(method);
2325 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2326 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2327 intDecl.getMethodId(method) + "(");
2328 for (int i = 0; i < methParams.size(); i++) {
2329 // Check for params with driver class types and exchange it
2330 // with its remote interface
2331 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2332 paramType = checkAndGetCplusType(paramType);
2333 // Check for arrays - translate into vector in C++
2334 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2335 print(paramComplete);
2336 // Check if this is the last element (don't print a comma)
2337 if (i != methParams.size() - 1) {
2347 * HELPER: writeMethodCplusInterface() writes the method of the interface
2349 private void writeMethodCplusInterface(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 = 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: generateEnumCplus() writes the enumeration declaration
2378 public void generateEnumCplus() throws IOException {
2380 // Create a new directory
2381 createDirectory(dir);
2382 for (String intface : mapIntfacePTH.keySet()) {
2383 // Get the right StructDecl
2384 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2385 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2386 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2387 // Iterate over enum declarations
2388 for (String enType : enumTypes) {
2389 // Open a new file to write into
2390 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2391 pw = new PrintWriter(new BufferedWriter(fw));
2392 // Write file headers
2393 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2394 println("#define _" + enType.toUpperCase() + "_HPP__");
2395 println("enum " + enType + " {");
2396 List<String> enumMembers = enumDecl.getMembers(enType);
2397 for (int i = 0; i < enumMembers.size(); i++) {
2399 String member = enumMembers.get(i);
2401 // Check if this is the last element (don't print a comma)
2402 if (i != enumMembers.size() - 1)
2410 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2417 * HELPER: generateStructCplus() writes the struct declaration
2419 public void generateStructCplus() throws IOException {
2421 // Create a new directory
2422 createDirectory(dir);
2423 for (String intface : mapIntfacePTH.keySet()) {
2424 // Get the right StructDecl
2425 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2426 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2427 List<String> structTypes = structDecl.getStructTypes();
2428 // Iterate over enum declarations
2429 for (String stType : structTypes) {
2430 // Open a new file to write into
2431 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2432 pw = new PrintWriter(new BufferedWriter(fw));
2433 // Write file headers
2434 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2435 println("#define _" + stType.toUpperCase() + "_HPP__");
2436 println("using namespace std;");
2437 println("struct " + stType + " {");
2438 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2439 List<String> structMembers = structDecl.getMembers(stType);
2440 for (int i = 0; i < structMembers.size(); i++) {
2442 String memberType = structMemberTypes.get(i);
2443 String member = structMembers.get(i);
2444 String structTypeC = checkAndGetCplusType(memberType);
2445 String structComplete = checkAndGetCplusArray(structTypeC, member);
2446 println(structComplete + ";");
2451 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2458 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2460 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2461 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2462 * The local interface has to be the input parameter for the stub and the stub
2463 * interface has to be the input parameter for the local class.
2465 public void generateCplusLocalInterfaces() throws IOException {
2467 // Create a new directory
2468 createDirectory(dir);
2469 for (String intface : mapIntfacePTH.keySet()) {
2470 // Open a new file to write into
2471 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2472 pw = new PrintWriter(new BufferedWriter(fw));
2473 // Write file headers
2474 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2475 println("#define _" + intface.toUpperCase() + "_HPP__");
2476 println("#include <iostream>");
2477 // Pass in set of methods and get include classes
2478 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2479 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2480 List<String> methods = intDecl.getMethods();
2481 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2482 printIncludeStatements(includeClasses); println("");
2483 println("using namespace std;\n");
2484 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2485 if (!intface.equals(mainClass)) // Forward declare if not main class
2486 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2487 println("class " + intface); println("{");
2490 writeMethodCplusLocalInterface(methods, intDecl);
2494 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2500 * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2502 private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2504 Set<String> isDefined = new HashSet<String>();
2505 for (String method : methods) {
2507 List<String> methParams = intDecl.getMethodParams(method);
2508 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2509 for (int i = 0; i < methParams.size(); i++) {
2510 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2511 // Check if this has callback object
2512 if (callbackClasses.contains(paramType)) {
2513 if (!isDefined.contains(paramType)) {
2515 println("class " + getStubInterface(paramType) + ";\n");
2517 println("class " + paramType + ";\n");
2518 isDefined.add(paramType);
2527 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2529 * For C++ we use virtual classe as interface
2531 public void generateCPlusInterfaces() throws IOException {
2533 // Create a new directory
2534 String path = createDirectories(dir, subdir);
2535 for (String intface : mapIntfacePTH.keySet()) {
2537 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2538 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2540 // Open a new file to write into
2541 String newIntface = intMeth.getKey();
2542 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2543 pw = new PrintWriter(new BufferedWriter(fw));
2544 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2545 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2546 // Write file headers
2547 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2548 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2549 println("#include <iostream>");
2550 updateIntfaceObjIdMap(intface, newIntface);
2551 // Pass in set of methods and get import classes
2552 Set<String> methods = intMeth.getValue();
2553 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2554 printIncludeStatements(includeClasses); println("");
2555 println("using namespace std;\n");
2556 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2557 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2558 println("class " + newIntface);
2562 writeMethodCplusInterface(methods, intDecl);
2566 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2573 * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2575 private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2577 for (String method : methods) {
2579 List<String> methParams = intDecl.getMethodParams(method);
2580 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2581 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2582 intDecl.getMethodId(method) + "(");
2583 for (int i = 0; i < methParams.size(); i++) {
2585 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2586 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2587 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2588 print(methParamComplete);
2589 // Check if this is the last element (don't print a comma)
2590 if (i != methParams.size() - 1) {
2600 * HELPER: writeMethodCplusStub() writes the methods of the stub
2602 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2604 for (String method : methods) {
2606 List<String> methParams = intDecl.getMethodParams(method);
2607 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2608 // Print the mutex lock first
2609 int methodNumId = intDecl.getMethodNumId(method);
2610 String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2611 println("mutex " + mutexVar + ";");
2612 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2613 intDecl.getMethodId(method) + "(");
2614 boolean isCallbackMethod = false;
2615 Set<String> callbackType = new HashSet<String>();
2616 for (int i = 0; i < methParams.size(); i++) {
2618 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2619 // Check if this has callback object
2620 if (callbackClasses.contains(paramType)) {
2621 isCallbackMethod = true;
2622 //callbackType = paramType;
2623 callbackType.add(paramType);
2624 // Even if there're 2 callback arguments, we expect them to be of the same interface
2626 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2627 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2628 print(methParamComplete);
2629 // Check if this is the last element (don't print a comma)
2630 if (i != methParams.size() - 1) {
2635 println("lock_guard<mutex> guard(" + mutexVar + ");");
2636 if (isCallbackMethod)
2637 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2638 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2646 * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2648 private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2650 println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2651 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2652 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2653 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2654 println("rmiComm->decrementObjectIdCounter();");
2655 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2656 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2657 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2658 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter +
2659 ", skel" + counter +");");
2660 println("th" + counter + ".detach();");
2661 println("while(!skel" + counter + "->didInitWaitInvoke());");
2665 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2666 println("objIdSent" + counter + ".push_back(itId->second);");
2672 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2674 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2675 List<String> methPrmTypes, String method, Set<String> callbackType) {
2677 // Check if this is single object, array, or list of objects
2678 boolean isArrayOrList = false;
2679 String callbackParam = null;
2680 for (int i = 0; i < methParams.size(); i++) {
2681 String paramType = methPrmTypes.get(i);
2682 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2683 println("vector<int> objIdSent" + i + ";");
2684 String param = methParams.get(i);
2685 if (isArrayOrList(paramType, param)) { // Generate loop
2686 println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2687 writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2688 isArrayOrList = true;
2689 callbackParam = getSimpleIdentifier(param);
2691 writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2695 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2702 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2704 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2706 // Iterate and find enum declarations
2707 for (int i = 0; i < methParams.size(); i++) {
2708 String paramType = methPrmTypes.get(i);
2709 String param = methParams.get(i);
2710 if (isEnumClass(getGenericType(paramType))) {
2711 // Check if this is enum type
2712 if (isArrayOrList(paramType, param)) { // An array or vector
2713 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2714 println("vector<int> paramEnum" + i + "(len" + i + ");");
2715 println("for (int i = 0; i < len" + i + "; i++) {");
2716 println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2718 } else { // Just one element
2719 println("vector<int> paramEnum" + i + "(1);");
2720 println("paramEnum" + i + "[0] = (int) " + param + ";");
2728 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2730 private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2732 // Strips off array "[]" for return type
2733 String pureType = getSimpleArrayType(getGenericType(retType));
2734 // Take the inner type of generic
2735 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2736 pureType = getGenericType(retType);
2737 if (isEnumClass(pureType)) {
2738 // Check if this is enum type
2739 println("vector<int> retEnumInt;");
2740 println("void* retObj = &retEnumInt;");
2741 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2742 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2743 if (isArrayOrList(retType, retType)) { // An array or vector
2744 println("int retLen = retEnumInt.size();");
2745 println("vector<" + pureType + "> retVal(retLen);");
2746 println("for (int i = 0; i < retLen; i++) {");
2747 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2749 } else { // Just one element
2750 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2752 println("return retVal;");
2758 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2760 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2761 InterfaceDecl intDecl, String method) {
2763 // Iterate and find struct declarations
2764 for (int i = 0; i < methParams.size(); i++) {
2765 String paramType = methPrmTypes.get(i);
2766 String param = methParams.get(i);
2767 String simpleType = getGenericType(paramType);
2768 if (isStructClass(simpleType)) {
2769 // Check if this is enum type
2770 println("int numParam" + i + " = 1;");
2771 int methodNumId = intDecl.getMethodNumId(method);
2772 String helperMethod = methodNumId + "struct" + i;
2773 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2774 //println("string retTypeStruct" + i + " = \"void\";");
2775 println("string paramClsStruct" + i + "[] = { \"int\" };");
2776 print("int structLen" + i + " = ");
2777 if (isArrayOrList(paramType, param)) { // An array
2778 println(getSimpleArrayType(param) + ".size();");
2779 } else { // Just one element
2782 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2783 println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
2784 ", paramClsStruct" + i + ", paramObjStruct" + i +
2785 ", numParam" + i + ");\n");
2792 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2794 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2796 // Iterate and find struct declarations - count number of params
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 int members = getNumOfMembers(simpleType);
2803 if (isArrayOrList(paramType, param)) { // An array or list
2804 String structLen = getSimpleIdentifier(param) + ".size()";
2805 print(members + "*" + structLen);
2807 print(Integer.toString(members));
2810 if (i != methParams.size() - 1) {
2818 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2820 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2822 // Get the struct declaration for this struct and generate initialization code
2823 StructDecl structDecl = getStructDecl(simpleType);
2824 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2825 List<String> members = structDecl.getMembers(simpleType);
2826 if (isArrayOrList(paramType, param)) { // An array or list
2827 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2829 if (isArrayOrList(paramType, param)) { // An array or list
2830 for (int i = 0; i < members.size(); i++) {
2831 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2832 println("paramCls[pos] = \"" + prmTypeC + "\";");
2833 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2834 print(getSimpleIdentifier(members.get(i)));
2838 } else { // Just one struct element
2839 for (int i = 0; i < members.size(); i++) {
2840 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2841 println("paramCls[pos] = \"" + prmTypeC + "\";");
2842 print("paramObj[pos++] = &" + param + ".");
2843 print(getSimpleIdentifier(members.get(i)));
2851 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2853 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2855 print("int numParam = ");
2856 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2858 println("void* paramObj[numParam];");
2859 println("string paramCls[numParam];");
2860 println("int pos = 0;");
2861 // Iterate again over the parameters
2862 for (int i = 0; i < methParams.size(); i++) {
2863 String paramType = methPrmTypes.get(i);
2864 String param = methParams.get(i);
2865 String simpleType = getGenericType(paramType);
2866 if (isStructClass(simpleType)) {
2867 writeStructMembersCplusStub(simpleType, paramType, param);
2868 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2869 println("paramCls[pos] = \"int\";");
2870 println("paramObj[pos++] = &___paramCB" + i + ";");
2872 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2873 println("paramCls[pos] = \"" + prmTypeC + "\";");
2874 print("paramObj[pos++] = &");
2875 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2884 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2886 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2888 // Get the struct declaration for this struct and generate initialization code
2889 StructDecl structDecl = getStructDecl(simpleType);
2890 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2891 List<String> members = structDecl.getMembers(simpleType);
2892 if (isArrayOrList(retType, retType)) { // An array or list
2893 println("for(int i = 0; i < retLen; i++) {");
2895 if (isArrayOrList(retType, retType)) { // An array or list
2896 for (int i = 0; i < members.size(); i++) {
2897 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2898 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2899 println(" = retParam" + i + "[i];");
2902 } else { // Just one struct element
2903 for (int i = 0; i < members.size(); i++) {
2904 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2905 print("structRet." + getSimpleIdentifier(members.get(i)));
2906 println(" = retParam" + i + ";");
2909 println("return structRet;");
2914 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2916 private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2918 // Minimum retLen is 1 if this is a single struct object
2919 println("int retLen = 0;");
2920 println("void* retLenObj = { &retLen };");
2921 // Handle the returned struct!!!
2922 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2923 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2924 int numMem = getNumOfMembers(simpleType);
2925 println("int numRet = " + numMem + "*retLen;");
2926 println("string retCls[numRet];");
2927 println("void* retObj[numRet];");
2928 StructDecl structDecl = getStructDecl(simpleType);
2929 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2930 List<String> members = structDecl.getMembers(simpleType);
2932 if (isArrayOrList(retType, retType)) { // An array or list
2933 for (int i = 0; i < members.size(); i++) {
2934 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2935 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2936 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2938 } else { // Just one struct element
2939 for (int i = 0; i < members.size(); i++) {
2940 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2941 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2942 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2945 println("int retPos = 0;");
2946 // Get the struct declaration for this struct and generate initialization code
2947 if (isArrayOrList(retType, retType)) { // An array or list
2948 println("for(int i = 0; i < retLen; i++) {");
2949 for (int i = 0; i < members.size(); i++) {
2950 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2951 println("retCls[retPos] = \"" + prmTypeC + "\";");
2952 println("retObj[retPos++] = &retParam" + i + "[i];");
2955 } else { // Just one struct element
2956 for (int i = 0; i < members.size(); i++) {
2957 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2958 println("retCls[retPos] = \"" + prmTypeC + "\";");
2959 println("retObj[retPos++] = &retParam" + i + ";");
2962 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2963 if (isArrayOrList(retType, retType)) { // An array or list
2964 println("vector<" + simpleType + "> structRet(retLen);");
2966 println(simpleType + " structRet;");
2967 writeStructRetMembersCplusStub(simpleType, retType);
2972 * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
2974 private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
2976 println("// Waiting for return value");
2977 int methodNumId = intDecl.getMethodNumId(method);
2978 println("while (!retValueReceived" + methodNumId + ");");
2979 println(getReturnValue);
2980 println("retValueReceived" + methodNumId + " = false;");
2981 println("didGetReturnBytes.exchange(true);\n");
2986 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
2988 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2989 List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
2991 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
2992 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2993 String retType = intDecl.getMethodType(method);
2994 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
2995 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
2996 // Generate array of parameter types
2997 if (isStructPresent(methParams, methPrmTypes)) {
2998 writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
3000 println("int numParam = " + methParams.size() + ";");
3001 print("string paramCls[] = { ");
3002 for (int i = 0; i < methParams.size(); i++) {
3003 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3004 if (checkCallbackType(paramType, callbackType)) {
3007 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3008 print("\"" + paramTypeC + "\"");
3010 // Check if this is the last element (don't print a comma)
3011 if (i != methParams.size() - 1) {
3016 // Generate array of parameter objects
3017 print("void* paramObj[] = { ");
3018 for (int i = 0; i < methParams.size(); i++) {
3019 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3020 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3021 print("&___paramCB" + i);
3023 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3024 // Check if this is the last element (don't print a comma)
3025 if (i != methParams.size() - 1) {
3031 // Check if this is "void"
3032 if (retType.equals("void")) {
3033 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3034 } else { // We do have a return value
3035 // Generate array of parameter types
3036 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3037 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3039 // Check if the return value NONPRIMITIVES
3040 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3041 checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3043 //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3044 if (isArrayOrList(retType,retType))
3045 println(checkAndGetCplusType(retType) + " retVal;");
3047 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3049 println("void* retObj = &retVal;");
3050 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3051 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3052 println("return retVal;");
3060 * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3062 private void writePropertiesCplusPermission(String intface) {
3064 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3065 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3066 String newIntface = intMeth.getKey();
3067 int newObjectId = getNewIntfaceObjectId(newIntface);
3068 println("static set<int> set" + newObjectId + "Allowed;");
3073 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3075 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
3076 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3078 println("IoTRMIComm *rmiComm;");
3079 // Get the object Id
3080 Integer objId = mapIntfaceObjId.get(intface);
3081 println("int objectId = " + objId + ";");
3082 println("// Synchronization variables");
3083 for (String method : methods) {
3084 // Generate AtomicBooleans for methods that have return values
3085 String returnType = intDecl.getMethodType(method);
3086 int methodNumId = intDecl.getMethodNumId(method);
3087 if (!returnType.equals("void")) {
3088 println("bool retValueReceived" + methodNumId + " = false;");
3096 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3098 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
3099 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3101 println(newStubClass + "::" + newStubClass +
3102 "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3103 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3104 // Register the AtomicBoolean variables
3105 for (String method : methods) {
3106 // Generate AtomicBooleans for methods that have return values
3107 String returnType = intDecl.getMethodType(method);
3108 int methodNumId = intDecl.getMethodNumId(method);
3109 if (!returnType.equals("void")) {
3110 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3113 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3119 * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3121 private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
3122 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3124 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3125 println("rmiComm = _rmiComm;");
3126 println("objectId = _objectId;");
3127 // Register the AtomicBoolean variables
3128 for (String method : methods) {
3129 // Generate AtomicBooleans for methods that have return values
3130 String returnType = intDecl.getMethodType(method);
3131 int methodNumId = intDecl.getMethodNumId(method);
3132 if (!returnType.equals("void")) {
3133 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3141 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3143 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3145 println(newStubClass + "::~" + newStubClass + "() {");
3146 println("if (rmiComm != NULL) {");
3147 println("delete rmiComm;");
3148 println("rmiComm = NULL;");
3156 * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3158 public void generateCPlusStubClassesHpp() throws IOException {
3160 // Create a new directory
3161 String path = createDirectories(dir, subdir);
3162 for (String intface : mapIntfacePTH.keySet()) {
3164 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3165 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3166 // Open a new file to write into
3167 String newIntface = intMeth.getKey();
3168 String newStubClass = newIntface + "_Stub";
3169 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3170 pw = new PrintWriter(new BufferedWriter(fw));
3171 // Write file headers
3172 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3173 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3174 println("#include <iostream>");
3175 // Find out if there are callback objects
3176 Set<String> methods = intMeth.getValue();
3177 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3178 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3179 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3180 boolean callbackExist = !callbackClasses.isEmpty();
3181 println("#include <thread>");
3182 println("#include <mutex>");
3183 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3184 printIncludeStatements(stdIncludeClasses); println("");
3185 println("#include \"" + newIntface + ".hpp\""); println("");
3186 println("using namespace std;"); println("");
3187 println("class " + newStubClass + " : public " + newIntface); println("{");
3188 println("private:\n");
3189 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3190 println("public:\n");
3191 // Add default constructor and destructor
3192 println(newStubClass + "();");
3194 println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3195 println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3196 println("~" + newStubClass + "();");
3198 writeMethodDeclCplusStub(methods, intDecl);
3199 print("}"); println(";");
3202 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3209 * writeStubExternalCFunctions() generate external functions for .so file
3211 public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3213 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3214 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3215 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " +
3216 "*((int*) params[3]), (bool*) params[4]);");
3218 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3219 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3220 println("delete obj;");
3222 println("extern \"C\" void init" + newStubClass + "(void* t) {");
3228 * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3230 public void generateCPlusStubClassesCpp() throws IOException {
3232 // Create a new directory
3233 String path = createDirectories(dir, subdir);
3234 for (String intface : mapIntfacePTH.keySet()) {
3236 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3237 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3238 // Open a new file to write into
3239 String newIntface = intMeth.getKey();
3240 String newStubClass = newIntface + "_Stub";
3241 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3242 pw = new PrintWriter(new BufferedWriter(fw));
3243 // Write file headers
3244 println("#include <iostream>");
3245 // Find out if there are callback objects
3246 Set<String> methods = intMeth.getValue();
3247 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3248 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3249 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3250 boolean callbackExist = !callbackClasses.isEmpty();
3251 println("#include \"" + newStubClass + ".hpp\""); println("");
3252 for(String str: callbackClasses) {
3253 if (intface.equals(mainClass))
3254 println("#include \"" + str + "_Skeleton.cpp\"\n");
3256 println("#include \"" + str + "_Skeleton.hpp\"\n");
3258 println("using namespace std;"); println("");
3259 // Add default constructor and destructor
3260 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3261 writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3262 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3264 writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3265 // Write external functions for .so file
3266 writeStubExternalCFunctions(newStubClass);
3267 // TODO: Remove this later
3268 if (intface.equals(mainClass)) {
3269 println("int main() {");
3270 println("return 0;");
3274 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3281 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3283 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3285 println(intface + " *mainObj;");
3286 println("IoTRMIComm *rmiComm;");
3287 println("char* methodBytes;");
3288 println("int methodLen;");
3289 Integer objId = mapIntfaceObjId.get(intface);
3290 println("int objectId = " + objId + ";");
3291 // Keep track of object Ids of all stubs registered to this interface
3292 writePropertiesCplusPermission(intface);
3293 println("// Synchronization variables");
3294 println("bool methodReceived = false;");
3295 println("bool didAlreadyInitWaitInvoke = false;");
3301 * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3303 private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3306 println("int " + newSkelClass + "::objIdCnt = 0;");
3311 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3313 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3315 // Keep track of object Ids of all stubs registered to this interface
3316 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3317 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3318 String newIntface = intMeth.getKey();
3319 int newObjectId = getNewIntfaceObjectId(newIntface);
3320 print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3321 Set<String> methodIds = intMeth.getValue();
3323 for (String methodId : methodIds) {
3324 int methodNumId = intDecl.getMethodNumId(methodId);
3325 print(Integer.toString(methodNumId));
3326 // Check if this is the last element (don't print a comma)
3327 if (i != methodIds.size() - 1) {
3338 * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3340 private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3342 // Use this set to handle two same methodIds
3343 for (String method : methods) {
3344 List<String> methParams = intDecl.getMethodParams(method);
3345 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3346 // Check for params with structs
3347 for (int i = 0; i < methParams.size(); i++) {
3348 String paramType = methPrmTypes.get(i);
3349 String param = methParams.get(i);
3350 String simpleType = getGenericType(paramType);
3351 if (isStructClass(simpleType)) {
3352 int methodNumId = intDecl.getMethodNumId(method);
3353 String helperMethod = methodNumId + "struct" + i;
3354 int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3355 // Iterate over interfaces to give permissions to
3356 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3357 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3358 String newIntface = intMeth.getKey();
3359 int newObjectId = getNewIntfaceObjectId(newIntface);
3360 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3369 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3371 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3373 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3374 println("bool _bResult = false;");
3375 println("mainObj = _mainObj;");
3376 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3377 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3378 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3379 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3380 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3381 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3382 println("th1.join();");
3388 * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3390 private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3392 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3393 println("bool _bResult = false;");
3394 println("mainObj = _mainObj;");
3395 println("rmiComm = _rmiComm;");
3396 println("objectId = _objectId;");
3397 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3398 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3404 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3406 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3408 println(newSkelClass + "::~" + newSkelClass + "() {");
3409 println("if (rmiComm != NULL) {");
3410 println("delete rmiComm;");
3411 println("rmiComm = NULL;");
3419 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3421 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3423 if (methodType.equals("void"))
3424 print("mainObj->" + methodId + "(");
3426 print("return mainObj->" + methodId + "(");
3427 for (int i = 0; i < methParams.size(); i++) {
3429 print(getSimpleIdentifier(methParams.get(i)));
3430 // Check if this is the last element (don't print a comma)
3431 if (i != methParams.size() - 1) {
3440 * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3442 private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3443 Set<String> callbackClasses) {
3445 for (String method : methods) {
3447 List<String> methParams = intDecl.getMethodParams(method);
3448 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3449 String methodId = intDecl.getMethodId(method);
3450 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3451 print(methodType + " " + methodId + "(");
3452 boolean isCallbackMethod = false;
3453 String callbackType = null;
3454 for (int i = 0; i < methParams.size(); i++) {
3456 String origParamType = methPrmTypes.get(i);
3457 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3458 isCallbackMethod = true;
3459 callbackType = origParamType;
3461 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3462 String methPrmType = checkAndGetCplusType(paramType);
3463 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3464 print(methParamComplete);
3465 // Check if this is the last element (don't print a comma)
3466 if (i != methParams.size() - 1) {
3476 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3478 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3480 for (String method : methods) {
3482 List<String> methParams = intDecl.getMethodParams(method);
3483 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3484 String methodId = intDecl.getMethodId(method);
3485 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3486 print(methodType + " " + newSkelClass + "::" + methodId + "(");
3487 for (int i = 0; i < methParams.size(); i++) {
3489 String origParamType = methPrmTypes.get(i);
3490 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3491 String methPrmType = checkAndGetCplusType(paramType);
3492 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3493 print(methParamComplete);
3494 // Check if this is the last element (don't print a comma)
3495 if (i != methParams.size() - 1) {
3500 // Now, write the body of skeleton!
3501 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3508 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3510 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3512 for (int i = 0; i < methParams.size(); i++) {
3513 String paramType = methPrmTypes.get(i);
3514 String param = methParams.get(i);
3515 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3516 println("vector<int> numStubIdArray" + i + ";");
3522 * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3524 private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
3526 println(exchParamType + "* newStub" + counter + " = NULL;");
3527 println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
3528 println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
3529 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
3530 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
3531 println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
3532 println("rmiComm->decrementObjectIdCounter();");
3535 println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
3541 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3543 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3545 // Iterate over callback objects
3546 for (int i = 0; i < methParams.size(); i++) {
3547 String paramType = methPrmTypes.get(i);
3548 String param = methParams.get(i);
3549 // Generate a loop if needed
3550 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3551 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3552 if (isArrayOrList(paramType, param)) {
3553 println("vector<" + exchParamType + "*> stub" + i + ";");
3554 println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3555 println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
3556 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3557 println("stub" + i + ".push_back(newStub" + i + ");");
3560 println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
3561 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3562 println(exchParamType + "* stub" + i + " = newStub" + i + ";");
3570 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3572 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3574 // Iterate and find enum declarations
3575 for (int i = 0; i < methParams.size(); i++) {
3576 String paramType = methPrmTypes.get(i);
3577 String param = methParams.get(i);
3578 String simpleType = getGenericType(paramType);
3579 if (isEnumClass(simpleType)) {
3580 // Check if this is enum type
3581 if (isArrayOrList(paramType, param)) { // An array
3582 println("int len" + i + " = paramEnumInt" + i + ".size();");
3583 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3584 println("for (int i=0; i < len" + i + "; i++) {");
3585 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3587 } else { // Just one element
3588 println(simpleType + " paramEnum" + i + ";");
3589 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3597 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3599 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3601 // Strips off array "[]" for return type
3602 String pureType = getSimpleArrayType(getGenericType(retType));
3603 // Take the inner type of generic
3604 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3605 pureType = getGenericType(retType);
3606 if (isEnumClass(pureType)) {
3607 // Check if this is enum type
3609 if (isArrayOrList(retType, retType)) { // An array
3610 println("int retLen = retEnum.size();");
3611 println("vector<int> retEnumInt(retLen);");
3612 println("for (int i=0; i < retLen; i++) {");
3613 println("retEnumInt[i] = (int) retEnum[i];");
3615 } else { // Just one element
3616 println("vector<int> retEnumInt(1);");
3617 println("retEnumInt[0] = (int) retEnum;");
3624 * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3626 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3627 Set<String> callbackClasses, String methodId) {
3629 print(methodId + "(");
3630 for (int i = 0; i < methParams.size(); i++) {
3631 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3632 if (callbackClasses.contains(paramType))
3634 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3635 print("paramEnum" + i);
3636 else if (isStructClass(getGenericType(paramType))) // Struct type
3637 print("paramStruct" + i);
3639 print(getSimpleIdentifier(methParams.get(i)));
3640 if (i != methParams.size() - 1) {
3649 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3651 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3652 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
3653 String methodId, Set<String> callbackClasses) {
3655 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3656 if (isCallbackMethod)
3657 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3658 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3659 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3660 // Check if this is "void"
3661 String retType = intDecl.getMethodType(method);
3662 // Check if this is "void"
3663 if (retType.equals("void")) {
3664 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3665 } else { // We do have a return value
3666 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3667 print(checkAndGetCplusType(retType) + " retEnum = ");
3668 else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3669 print(checkAndGetCplusType(retType) + " retStruct = ");
3671 print(checkAndGetCplusType(retType) + " retVal = ");
3672 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3673 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3674 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3675 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3676 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3677 println("void* retObj = &retEnumInt;");
3679 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3680 println("void* retObj = &retVal;");
3681 String retTypeC = checkAndGetCplusType(retType);
3682 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3683 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3685 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3691 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3693 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3694 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3696 // Generate array of parameter types
3697 boolean isCallbackMethod = false;
3698 Set<String> callbackType = new HashSet<String>();
3699 print("string paramCls[] = { ");
3700 for (int i = 0; i < methParams.size(); i++) {
3701 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3702 if (callbackClasses.contains(paramType)) {
3703 isCallbackMethod = true;
3704 callbackType.add(paramType);
3706 } else { // Generate normal classes if it's not a callback object
3707 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3708 print("\"" + paramTypeC + "\"");
3710 if (i != methParams.size() - 1) {
3715 println("int numParam = " + methParams.size() + ";");
3716 if (isCallbackMethod)
3717 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3718 // Generate parameters
3719 for (int i = 0; i < methParams.size(); i++) {
3720 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3721 if (!callbackClasses.contains(paramType)) {
3722 String methParamType = methPrmTypes.get(i);
3723 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
3724 // Check if this is enum type
3725 println("vector<int> paramEnumInt" + i + ";");
3727 String methPrmType = checkAndGetCplusType(methParamType);
3728 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3729 println(methParamComplete + ";");
3733 // Generate array of parameter objects
3734 print("void* paramObj[] = { ");
3735 for (int i = 0; i < methParams.size(); i++) {
3736 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3737 if (callbackClasses.contains(paramType))
3738 print("&numStubIdArray" + i);
3739 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3740 print("¶mEnumInt" + i);
3742 print("&" + getSimpleIdentifier(methParams.get(i)));
3743 if (i != methParams.size() - 1) {
3748 // Write the return value part
3749 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3750 callbackType, methodId, callbackClasses);
3755 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3757 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3758 String param, String method, InterfaceDecl intDecl, int iVar) {
3760 // Get the struct declaration for this struct and generate initialization code
3761 StructDecl structDecl = getStructDecl(simpleType);
3762 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3763 List<String> members = structDecl.getMembers(simpleType);
3764 int methodNumId = intDecl.getMethodNumId(method);
3765 String counter = "struct" + methodNumId + "Size" + iVar;
3767 if (isArrayOrList(paramType, param)) { // An array or list
3768 for (int i = 0; i < members.size(); i++) {
3769 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3770 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3771 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3773 } else { // Just one struct element
3774 for (int i = 0; i < members.size(); i++) {
3775 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3776 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3777 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3780 if (isArrayOrList(paramType, param)) { // An array or list
3781 println("for(int i = 0; i < " + counter + "; i++) {");
3783 if (isArrayOrList(paramType, param)) { // An array or list
3784 for (int i = 0; i < members.size(); i++) {
3785 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3786 println("paramCls[pos] = \"" + prmTypeC + "\";");
3787 println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
3790 } else { // Just one struct element
3791 for (int i = 0; i < members.size(); i++) {
3792 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3793 println("paramCls[pos] = \"" + prmTypeC + "\";");
3794 println("paramObj[pos++] = ¶m" + iVar + i + ";");
3801 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3803 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3804 List<String> methPrmTypes, String method) {
3806 for (int i = 0; i < methParams.size(); i++) {
3807 String paramType = methPrmTypes.get(i);
3808 String param = methParams.get(i);
3809 String simpleType = getGenericType(paramType);
3810 if (isStructClass(simpleType)) {
3811 int methodNumId = intDecl.getMethodNumId(method);
3812 String counter = "struct" + methodNumId + "Size" + i;
3814 if (isArrayOrList(paramType, param)) { // An array or list
3815 println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3817 println(simpleType + " paramStruct" + i + ";");
3818 // Initialize members
3819 StructDecl structDecl = getStructDecl(simpleType);
3820 List<String> members = structDecl.getMembers(simpleType);
3821 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3822 if (isArrayOrList(paramType, param)) { // An array or list
3823 println("for(int i = 0; i < " + counter + "; i++) {");
3824 for (int j = 0; j < members.size(); j++) {
3825 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3826 println(" = param" + i + j + "[i];");
3829 } else { // Just one struct element
3830 for (int j = 0; j < members.size(); j++) {
3831 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3832 println(" = param" + i + j + ";");
3841 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3843 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3845 // Minimum retLen is 1 if this is a single struct object
3846 if (isArrayOrList(retType, retType))
3847 println("int retLen = retStruct.size();");
3848 else // Just single struct object
3849 println("int retLen = 1;");
3850 println("void* retLenObj = &retLen;");
3851 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3852 int numMem = getNumOfMembers(simpleType);
3853 println("int numRetObj = " + numMem + "*retLen;");
3854 println("string retCls[numRetObj];");
3855 println("void* retObj[numRetObj];");
3856 println("int retPos = 0;");
3857 // Get the struct declaration for this struct and generate initialization code
3858 StructDecl structDecl = getStructDecl(simpleType);
3859 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3860 List<String> members = structDecl.getMembers(simpleType);
3861 if (isArrayOrList(retType, retType)) { // An array or list
3862 println("for(int i = 0; i < retLen; i++) {");
3863 for (int i = 0; i < members.size(); i++) {
3864 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3865 println("retCls[retPos] = \"" + prmTypeC + "\";");
3866 print("retObj[retPos++] = &retStruct[i].");
3867 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3871 } else { // Just one struct element
3872 for (int i = 0; i < members.size(); i++) {
3873 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3874 println("retCls[retPos] = \"" + prmTypeC + "\";");
3875 print("retObj[retPos++] = &retStruct.");
3876 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3885 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3887 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3888 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3890 // Generate array of parameter objects
3891 boolean isCallbackMethod = false;
3892 Set<String> callbackType = new HashSet<String>();
3893 print("int numParam = ");
3894 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3896 println("string paramCls[numParam];");
3897 println("void* paramObj[numParam];");
3898 println("int pos = 0;");
3899 // Iterate again over the parameters
3900 for (int i = 0; i < methParams.size(); i++) {
3901 String paramType = methPrmTypes.get(i);
3902 String param = methParams.get(i);
3903 String simpleType = getGenericType(paramType);
3904 if (isStructClass(simpleType)) {
3905 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3907 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3908 if (callbackClasses.contains(prmType)) {
3909 isCallbackMethod = true;
3910 callbackType.add(prmType);
3911 println("vector<int> numStubIdArray" + i + ";");
3912 println("paramCls[pos] = \"int*\";");
3913 println("paramObj[pos++] = &numStubIdArray" + i + ";");
3914 } else { // Generate normal classes if it's not a callback object
3915 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3916 if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
3917 println("vector<int> paramEnumInt" + i + ";");
3919 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3920 println(methParamComplete + ";");
3922 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3923 println("paramCls[pos] = \"" + prmTypeC + "\";");
3924 if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3925 println("paramObj[pos++] = ¶mEnumInt" + i + ";");
3927 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3931 // Write the return value part
3932 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3933 callbackType, methodId, callbackClasses);
3938 * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
3940 private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3942 // Use this set to handle two same methodIds
3943 Set<String> uniqueMethodIds = new HashSet<String>();
3944 for (String method : methods) {
3946 List<String> methParams = intDecl.getMethodParams(method);
3947 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3948 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
3949 String methodId = intDecl.getMethodId(method);
3951 String helperMethod = methodId;
3952 if (uniqueMethodIds.contains(methodId))
3953 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3955 uniqueMethodIds.add(methodId);
3956 String retType = intDecl.getMethodType(method);
3957 print(helperMethod + "(");
3958 boolean begin = true;
3959 for (int i = 0; i < methParams.size(); i++) { // Print size variables
3960 String paramType = methPrmTypes.get(i);
3961 String param = methParams.get(i);
3962 String simpleType = getGenericType(paramType);
3963 if (isStructClass(simpleType)) {
3964 if (!begin) // Generate comma for not the beginning variable
3968 int methodNumId = intDecl.getMethodNumId(method);
3969 print("int struct" + methodNumId + "Size" + i);
3972 println(", " + newSkelClass + "* skel);");
3974 String methodId = intDecl.getMethodId(method);
3976 String helperMethod = methodId;
3977 if (uniqueMethodIds.contains(methodId))
3978 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3980 uniqueMethodIds.add(methodId);
3981 // Check if this is "void"
3982 String retType = intDecl.getMethodType(method);
3983 println(helperMethod + "(" + newSkelClass + "* skel);");
3986 // Write method helper for structs
3987 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
3992 * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
3994 private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods,
3995 InterfaceDecl intDecl, String newSkelClass) {
3997 // Use this set to handle two same methodIds
3998 for (String method : methods) {
4000 List<String> methParams = intDecl.getMethodParams(method);
4001 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4002 // Check for params with structs
4003 for (int i = 0; i < methParams.size(); i++) {
4004 String paramType = methPrmTypes.get(i);
4005 String param = methParams.get(i);
4006 String simpleType = getGenericType(paramType);
4007 if (isStructClass(simpleType)) {
4008 int methodNumId = intDecl.getMethodNumId(method);
4010 String helperMethod = methodNumId + "struct" + i;
4011 println(helperMethod + "(" + newSkelClass + "* skel);");
4019 * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4021 private void writeMethodBytesCopy() {
4023 println("char* localMethodBytes = new char[methodLen];");
4024 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4025 println("didGetMethodBytes.exchange(true);");
4030 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4032 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4033 Set<String> callbackClasses, String newSkelClass) {
4035 // Use this set to handle two same methodIds
4036 Set<String> uniqueMethodIds = new HashSet<String>();
4037 for (String method : methods) {
4039 List<String> methParams = intDecl.getMethodParams(method);
4040 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4041 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4042 String methodId = intDecl.getMethodId(method);
4043 print("void " + newSkelClass + "::___");
4044 String helperMethod = methodId;
4045 if (uniqueMethodIds.contains(methodId))
4046 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4048 uniqueMethodIds.add(methodId);
4049 String retType = intDecl.getMethodType(method);
4050 print(helperMethod + "(");
4051 boolean begin = true;
4052 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4053 String paramType = methPrmTypes.get(i);
4054 String param = methParams.get(i);
4055 String simpleType = getGenericType(paramType);
4056 if (isStructClass(simpleType)) {
4057 if (!begin) // Generate comma for not the beginning variable
4061 int methodNumId = intDecl.getMethodNumId(method);
4062 print("int struct" + methodNumId + "Size" + i);
4065 println(", " + newSkelClass + "* skel) {");
4066 writeMethodBytesCopy();
4067 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4068 println("delete[] localMethodBytes;");
4071 String methodId = intDecl.getMethodId(method);
4072 print("void " + newSkelClass + "::___");
4073 String helperMethod = methodId;
4074 if (uniqueMethodIds.contains(methodId))
4075 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4077 uniqueMethodIds.add(methodId);
4078 // Check if this is "void"
4079 String retType = intDecl.getMethodType(method);
4080 println(helperMethod + "(" + newSkelClass + "* skel) {");
4081 writeMethodBytesCopy();
4082 // Now, write the helper body of skeleton!
4083 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4084 println("delete[] localMethodBytes;");
4088 // Write method helper for structs
4089 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4094 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4096 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
4097 InterfaceDecl intDecl, String newSkelClass) {
4099 // Use this set to handle two same methodIds
4100 for (String method : methods) {
4102 List<String> methParams = intDecl.getMethodParams(method);
4103 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4104 // Check for params with structs
4105 for (int i = 0; i < methParams.size(); i++) {
4106 String paramType = methPrmTypes.get(i);
4107 String param = methParams.get(i);
4108 String simpleType = getGenericType(paramType);
4109 if (isStructClass(simpleType)) {
4110 int methodNumId = intDecl.getMethodNumId(method);
4111 print("int " + newSkelClass + "::___");
4112 String helperMethod = methodNumId + "struct" + i;
4113 println(helperMethod + "(" + newSkelClass + "* skel) {");
4114 // Now, write the helper body of skeleton!
4115 writeMethodBytesCopy();
4116 println("string paramCls[] = { \"int\" };");
4117 println("int numParam = 1;");
4118 println("int param0 = 0;");
4119 println("void* paramObj[] = { ¶m0 };");
4120 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4121 println("return param0;");
4122 println("delete[] localMethodBytes;");
4131 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4133 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
4134 InterfaceDecl intDecl) {
4136 // Use this set to handle two same methodIds
4137 for (String method : methods) {
4139 List<String> methParams = intDecl.getMethodParams(method);
4140 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4141 // Check for params with structs
4142 for (int i = 0; i < methParams.size(); i++) {
4143 String paramType = methPrmTypes.get(i);
4144 String param = methParams.get(i);
4145 String simpleType = getGenericType(paramType);
4146 if (isStructClass(simpleType)) {
4147 int methodNumId = intDecl.getMethodNumId(method);
4149 String helperMethod = methodNumId + "struct" + i;
4150 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4151 // Now, write the helper body of skeleton!
4152 println("string paramCls[] = { \"int\" };");
4153 println("int numParam = 1;");
4154 println("int param0 = 0;");
4155 println("void* paramObj[] = { ¶m0 };");
4156 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4157 println("return param0;");
4166 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4168 private void writeCplusMethodPermission(String intface) {
4170 // Get all the different stubs
4171 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4172 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4173 String newIntface = intMeth.getKey();
4174 int newObjectId = getNewIntfaceObjectId(newIntface);
4175 println("if (_objectId == objectId) {");
4176 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4177 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
4182 println("continue;");
4189 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4191 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4192 boolean callbackExist, String intface, String newSkelClass) {
4194 // Use this set to handle two same methodIds
4195 Set<String> uniqueMethodIds = new HashSet<String>();
4196 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4197 // Write variables here if we have callbacks or enums or structs
4198 writeCountVarStructSkeleton(methods, intDecl);
4199 println("skel->didAlreadyInitWaitInvoke = true;");
4200 println("while (true) {");
4201 println("if (!methodReceived) {");
4202 println("continue;");
4204 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4205 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4206 println("methodReceived = false;");
4207 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4208 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4209 // Generate permission check
4210 writeCplusMethodPermission(intface);
4211 println("switch (methodId) {");
4212 // Print methods and method Ids
4213 for (String method : methods) {
4214 String methodId = intDecl.getMethodId(method);
4215 int methodNumId = intDecl.getMethodNumId(method);
4216 println("case " + methodNumId + ": {");
4217 print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4218 String helperMethod = methodId;
4219 if (uniqueMethodIds.contains(methodId))
4220 helperMethod = helperMethod + methodNumId;
4222 uniqueMethodIds.add(methodId);
4223 print(helperMethod + ", skel, ");
4224 boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4228 println("th" + methodNumId + ".detach(); break;");
4231 writeMethodCallStructCplusSkeleton(methods, intDecl);
4232 println("default: ");
4233 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4242 * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4244 public void generateCplusSkeletonClassHpp() throws IOException {
4246 // Create a new directory
4247 String path = createDirectories(dir, subdir);
4248 for (String intface : mapIntfacePTH.keySet()) {
4249 // Open a new file to write into
4250 String newSkelClass = intface + "_Skeleton";
4251 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4252 pw = new PrintWriter(new BufferedWriter(fw));
4253 // Write file headers
4254 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4255 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4256 println("#include <iostream>");
4257 println("#include \"" + intface + ".hpp\"\n");
4258 // Pass in set of methods and get import classes
4259 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4260 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4261 List<String> methods = intDecl.getMethods();
4262 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4263 printIncludeStatements(stdIncludeClasses); println("");
4264 println("using namespace std;\n");
4265 // Find out if there are callback objects
4266 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4267 boolean callbackExist = !callbackClasses.isEmpty();
4268 // Write class header
4269 println("class " + newSkelClass + " : public " + intface); println("{");
4270 println("private:\n");
4272 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4273 println("public:\n");
4274 // Write constructors
4275 println(newSkelClass + "();");
4276 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4277 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4278 // Write deconstructor
4279 println("~" + newSkelClass + "();");
4280 // Write method declarations
4281 println("bool didInitWaitInvoke();");
4282 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4283 // Write method helper declarations
4284 writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
4285 // Write waitRequestInvokeMethod() declaration - main loop
4286 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4288 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4291 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4296 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4298 private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4300 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4301 println("return didAlreadyInitWaitInvoke;");
4307 * writeSkelExternalCFunctions() generate external functions for .so file
4309 public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4311 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4312 println("// Args: *_mainObj, int _portSend, int _portRecv");
4313 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
4315 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4316 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4317 println("delete obj;");
4319 println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4325 * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4327 public void generateCplusSkeletonClassCpp() throws IOException {
4329 // Create a new directory
4330 String path = createDirectories(dir, subdir);
4331 for (String intface : mapIntfacePTH.keySet()) {
4332 // Open a new file to write into
4333 String newSkelClass = intface + "_Skeleton";
4334 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4335 pw = new PrintWriter(new BufferedWriter(fw));
4336 // Write file headers
4337 println("#include <iostream>");
4338 println("#include \"" + newSkelClass + ".hpp\"\n");
4339 // Pass in set of methods and get import classes
4340 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4341 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4342 List<String> methods = intDecl.getMethods();
4343 // Find out if there are callback objects
4344 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4345 boolean callbackExist = !callbackClasses.isEmpty();
4346 for(String str: callbackClasses) {
4347 if (intface.equals(mainClass))
4348 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4350 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4352 println("using namespace std;\n");
4353 // Write constructor
4354 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4355 // Write callback constructor
4356 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4357 // Write deconstructor
4358 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4359 // Write didInitWaitInvoke() to return bool
4360 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4362 writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
4363 // Write method helper
4364 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4365 // Write waitRequestInvokeMethod() - main loop
4366 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4367 // Write external functions for .so file
4368 writeSkelExternalCFunctions(newSkelClass, intface);
4369 // TODO: Remove this later
4370 if (intface.equals(mainClass)) {
4371 println("int main() {");
4372 println("return 0;");
4376 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4382 * generateInitializer() generate initializer based on type
4384 public String generateCplusInitializer(String type) {
4386 // Generate dummy returns for now
4387 if (type.equals("short")||
4388 type.equals("int") ||
4389 type.equals("long") ||
4390 type.equals("float")||
4391 type.equals("double")) {
4394 } else if ( type.equals("String") ||
4395 type.equals("string")) {
4398 } else if ( type.equals("char") ||
4399 type.equals("byte")) {
4402 } else if ( type.equals("boolean")) {
4412 * setDirectory() sets a new directory for stub files
4414 public void setDirectory(String _subdir) {
4421 * printUsage() prints the usage of this compiler
4423 public static void printUsage() {
4425 System.out.println();
4426 System.out.println("Vigilia interface and stub compiler version 1.0");
4427 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4428 System.out.println("All rights reserved.");
4429 System.out.println("Usage:");
4430 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4431 System.out.println("\t\tDisplay this help texts\n\n");
4432 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4433 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4434 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4435 System.out.println("Options:");
4436 System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
4437 System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
4438 System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
4439 System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
4440 System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
4441 System.out.println();
4446 * parseFile() prepares Lexer and Parser objects, then parses the file
4448 public static ParseNode parseFile(String file) {
4450 ParseNode pn = null;
4452 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4453 ScannerBuffer lexer =
4454 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4455 Parser parse = new Parser(lexer,csf);
4456 pn = (ParseNode) parse.parse().value;
4457 } catch (Exception e) {
4458 e.printStackTrace();
4459 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4467 * Basic helper functions
4470 boolean newline=true;
4473 private void print(String str) {
4476 if (str.equals("}"))
4478 for(int i=0; i<tab; i++)
4488 * This function converts Java to C++ type for compilation
4490 private String convertType(String type) {
4492 if (mapPrimitives.containsKey(type))
4493 return mapPrimitives.get(type);
4500 * A collection of methods with print-to-file functionality
4502 private void println(String str) {
4505 if (str.contains("}") && !str.contains("{"))
4507 for(int i=0; i<tab; i++)
4516 private void updatetabbing(String str) {
4518 tablevel+=count(str,'{')-count(str,'}');
4522 private int count(String str, char key) {
4523 char[] array = str.toCharArray();
4525 for(int i=0; i<array.length; i++) {
4526 if (array[i] == key)
4533 private void createDirectory(String dirName) {
4535 File file = new File(dirName);
4536 if (!file.exists()) {
4538 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4540 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4543 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4548 // Create a directory and possibly a sub directory
4549 private String createDirectories(String dir, String subdir) {
4552 createDirectory(path);
4553 if (subdir != null) {
4554 path = path + "/" + subdir;
4555 createDirectory(path);
4561 // Inserting array members into a Map object
4562 // that maps arrKey to arrVal objects
4563 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4565 for(int i = 0; i < arrKey.length; i++) {
4567 map.put(arrKey[i], arrVal[i]);
4572 // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4573 // Throw an error if the new interface is not found!
4574 // Basically the compiler needs to parse the policy (and requires) files for callback class first
4575 private int getNewIntfaceObjectId(String newIntface) {
4577 int retObjId = mapNewIntfaceObjId.get(newIntface);
4582 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4583 private ParamCategory getParamCategory(String paramType) {
4585 if (mapPrimitives.containsKey(paramType)) {
4586 return ParamCategory.PRIMITIVES;
4587 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4588 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4589 return ParamCategory.NONPRIMITIVES;
4590 } else if (isEnumClass(paramType)) {
4591 return ParamCategory.ENUM;
4592 } else if (isStructClass(paramType)) {
4593 return ParamCategory.STRUCT;
4595 return ParamCategory.USERDEFINED;
4599 // Return full class name for non-primitives to generate Java import statements
4600 // e.g. java.util.Set for Set
4601 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4603 return mapNonPrimitivesJava.get(paramNonPrimitives);
4607 // Return full class name for non-primitives to generate Cplus include statements
4608 // e.g. #include <set> for Set
4609 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4611 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4615 // Get simple types, e.g. HashSet for HashSet<...>
4616 // Basically strip off the "<...>"
4617 private String getSimpleType(String paramType) {
4619 // Check if this is generics
4620 if(paramType.contains("<")) {
4621 String[] type = paramType.split("<");
4628 // Generate a set of standard classes for import statements
4629 private List<String> getStandardJavaIntfaceImportClasses() {
4631 List<String> importClasses = new ArrayList<String>();
4632 // Add the standard list first
4633 importClasses.add("java.util.List");
4634 importClasses.add("java.util.ArrayList");
4636 return importClasses;
4640 // Generate a set of standard classes for import statements
4641 private List<String> getStandardJavaImportClasses() {
4643 List<String> importClasses = new ArrayList<String>();
4644 // Add the standard list first
4645 importClasses.add("java.io.IOException");
4646 importClasses.add("java.util.List");
4647 importClasses.add("java.util.ArrayList");
4648 importClasses.add("java.util.Arrays");
4649 importClasses.add("java.util.Map");
4650 importClasses.add("java.util.HashMap");
4651 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4652 importClasses.add("iotrmi.Java.IoTRMIComm");
4653 importClasses.add("iotrmi.Java.IoTRMICommClient");
4654 importClasses.add("iotrmi.Java.IoTRMICommServer");
4655 importClasses.add("iotrmi.Java.IoTRMIUtil");
4657 return importClasses;
4661 // Generate a set of standard classes for import statements
4662 private List<String> getStandardCplusIncludeClasses() {
4664 List<String> importClasses = new ArrayList<String>();
4665 // Add the standard list first
4666 importClasses.add("<vector>");
4667 importClasses.add("<set>");
4668 importClasses.add("\"IoTRMIComm.hpp\"");
4669 importClasses.add("\"IoTRMICommClient.hpp\"");
4670 importClasses.add("\"IoTRMICommServer.hpp\"");
4672 return importClasses;
4676 // Combine all classes for import statements
4677 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4679 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4680 // Iterate over the list of import classes
4681 for (String str : libClasses) {
4682 if (!allLibClasses.contains(str)) {
4683 allLibClasses.add(str);
4686 return allLibClasses;
4691 // Generate a set of classes for import statements
4692 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4694 Set<String> importClasses = new HashSet<String>();
4695 for (String method : methods) {
4696 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4697 for (String paramType : methPrmTypes) {
4699 String simpleType = getSimpleType(paramType);
4700 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4701 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4705 return importClasses;
4709 // Handle and return the correct enum declaration
4710 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4711 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4713 // Strips off array "[]" for return type
4714 String pureType = getSimpleArrayType(type);
4715 // Take the inner type of generic
4716 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4717 pureType = getTypeOfGeneric(type)[0];
4718 if (isEnumClass(pureType)) {
4719 String enumType = intDecl.getInterface() + "." + type;
4726 // Handle and return the correct type
4727 private String getEnumParam(String type, String param, int i) {
4729 // Strips off array "[]" for return type
4730 String pureType = getSimpleArrayType(type);
4731 // Take the inner type of generic
4732 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4733 pureType = getTypeOfGeneric(type)[0];
4734 if (isEnumClass(pureType)) {
4735 String enumParam = "paramEnum" + i;
4742 // Handle and return the correct enum declaration translate into int[]
4743 private String getEnumType(String type) {
4745 // Strips off array "[]" for return type
4746 String pureType = getSimpleArrayType(type);
4747 // Take the inner type of generic
4748 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4749 pureType = getGenericType(type);
4750 if (isEnumClass(pureType)) {
4751 String enumType = "int[]";
4757 // Handle and return the correct enum declaration translate into int* for C
4758 private String getEnumCplusClsType(String type) {
4760 // Strips off array "[]" for return type
4761 String pureType = getSimpleArrayType(type);
4762 // Take the inner type of generic
4763 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4764 pureType = getGenericType(type);
4765 if (isEnumClass(pureType)) {
4766 String enumType = "int*";
4773 // Handle and return the correct struct declaration
4774 private String getStructType(String type) {
4776 // Strips off array "[]" for return type
4777 String pureType = getSimpleArrayType(type);
4778 // Take the inner type of generic
4779 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4780 pureType = getGenericType(type);
4781 if (isStructClass(pureType)) {
4782 String structType = "int";
4789 // Check if this an enum declaration
4790 private boolean isEnumClass(String type) {
4792 // Just iterate over the set of interfaces
4793 for (String intface : mapIntfacePTH.keySet()) {
4794 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4795 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4796 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4797 if (setEnumDecl.contains(type))
4804 // Check if this an struct declaration
4805 private boolean isStructClass(String type) {
4807 // Just iterate over the set of interfaces
4808 for (String intface : mapIntfacePTH.keySet()) {
4809 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4810 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4811 List<String> listStructDecl = structDecl.getStructTypes();
4812 if (listStructDecl.contains(type))
4819 // Return a struct declaration
4820 private StructDecl getStructDecl(String type) {
4822 // Just iterate over the set of interfaces
4823 for (String intface : mapIntfacePTH.keySet()) {
4824 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4825 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4826 List<String> listStructDecl = structDecl.getStructTypes();
4827 if (listStructDecl.contains(type))
4834 // Return number of members (-1 if not found)
4835 private int getNumOfMembers(String type) {
4837 // Just iterate over the set of interfaces
4838 for (String intface : mapIntfacePTH.keySet()) {
4839 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4840 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4841 List<String> listStructDecl = structDecl.getStructTypes();
4842 if (listStructDecl.contains(type))
4843 return structDecl.getNumOfMembers(type);
4849 // Generate a set of classes for include statements
4850 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4852 Set<String> includeClasses = new HashSet<String>();
4853 for (String method : methods) {
4855 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4856 List<String> methParams = intDecl.getMethodParams(method);
4857 for (int i = 0; i < methPrmTypes.size(); i++) {
4859 String genericType = getGenericType(methPrmTypes.get(i));
4860 String simpleType = getSimpleType(methPrmTypes.get(i));
4861 String param = methParams.get(i);
4862 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4863 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4864 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4866 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4867 // For original interface, we need it exchanged... not for stub interfaces
4869 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4870 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4872 //includeClasses.add("\"" + simpleType + ".hpp\"");
4873 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4876 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4877 includeClasses.add("\"" + genericType + ".hpp\"");
4879 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4880 includeClasses.add("\"" + genericType + ".hpp\"");
4882 if (param.contains("[]")) {
4883 // Check if this is array for C++; translate into vector
4884 includeClasses.add("<vector>");
4888 return includeClasses;
4892 // Generate a set of callback classes
4893 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4895 Set<String> callbackClasses = new HashSet<String>();
4896 for (String method : methods) {
4898 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4899 List<String> methParams = intDecl.getMethodParams(method);
4900 for (int i = 0; i < methPrmTypes.size(); i++) {
4902 String type = methPrmTypes.get(i);
4903 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4904 callbackClasses.add(type);
4905 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4906 // Can be a List<...> of callback objects ...
4907 String genericType = getTypeOfGeneric(type)[0];
4908 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4909 callbackClasses.add(type);
4914 return callbackClasses;
4918 // Check if this is a callback class
4919 private boolean isCallbackClass(String className) {
4921 Set<String> intfaceSet = mapIntDeclHand.keySet();
4922 for(String intface : intfaceSet) {
4924 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4925 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4926 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4927 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4928 Set<String> methods = intMeth.getValue();
4929 for (String method : methods) {
4931 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4932 List<String> methParams = intDecl.getMethodParams(method);
4933 for (int i = 0; i < methPrmTypes.size(); i++) {
4935 String type = methPrmTypes.get(i);
4936 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4937 // Final check to see if this is the searched class
4938 if (type.equals(className))
4940 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4941 // Can be a List<...> of callback objects ...
4942 String genericType = getTypeOfGeneric(type)[0];
4943 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4944 if (type.equals(className))
4957 // Print import statements into file
4958 private void printImportStatements(Collection<String> importClasses) {
4960 for(String cls : importClasses) {
4961 println("import " + cls + ";");
4966 // Print include statements into file
4967 private void printIncludeStatements(Collection<String> includeClasses) {
4969 for(String cls : includeClasses) {
4970 println("#include " + cls);
4975 // Get the C++ version of a non-primitive type
4976 // e.g. set for Set and map for Map
4977 // Input nonPrimitiveType has to be generics in format
4978 private String[] getTypeOfGeneric(String nonPrimitiveType) {
4980 // Handle <, >, and , for 2-type generic/template
4981 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
4986 // Gets generic type inside "<" and ">"
4987 private String getGenericType(String type) {
4989 // Handle <, >, and , for 2-type generic/template
4990 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4991 String[] substr = type.split("<")[1].split(">")[0].split(",");
4998 // This helper function strips off array declaration, e.g. int[] becomes int
4999 private String getSimpleArrayType(String type) {
5001 // Handle [ for array declaration
5002 String substr = type;
5003 if (type.contains("[]")) {
5004 substr = type.split("\\[\\]")[0];
5010 // This helper function strips off array declaration, e.g. D[] becomes D
5011 private String getSimpleIdentifier(String ident) {
5013 // Handle [ for array declaration
5014 String substr = ident;
5015 if (ident.contains("[]")) {
5016 substr = ident.split("\\[\\]")[0];
5022 // Checks and gets type in C++
5023 private String checkAndGetCplusType(String paramType) {
5025 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
5026 return convertType(paramType);
5027 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
5029 // Check for generic/template format
5030 if (paramType.contains("<") && paramType.contains(">")) {
5032 String genericClass = getSimpleType(paramType);
5033 String genericType = getGenericType(paramType);
5034 String cplusTemplate = null;
5035 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
5036 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
5037 cplusTemplate = cplusTemplate + "<" + genericType + "*>";
5039 cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
5041 return cplusTemplate;
5043 return getNonPrimitiveCplusClass(paramType);
5044 } else if(paramType.contains("[]")) { // Array type (used for return type only)
5045 String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
5047 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5048 return paramType + "*";
5050 // Just return it as is if it's not non-primitives
5055 // Detect array declaration, e.g. int A[],
5056 // then generate "int A[]" in C++ as "vector<int> A"
5057 private String checkAndGetCplusArray(String paramType, String param) {
5059 String paramComplete = null;
5060 // Check for array declaration
5061 if (param.contains("[]")) {
5062 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5064 // Just return it as is if it's not an array
5065 paramComplete = paramType + " " + param;
5067 return paramComplete;
5071 // Detect array declaration, e.g. int A[],
5072 // then generate "int A[]" in C++ as "vector<int> A"
5073 // This method just returns the type
5074 private String checkAndGetCplusArrayType(String paramType) {
5076 String paramTypeRet = null;
5077 // Check for array declaration
5078 if (paramType.contains("[]")) {
5079 String type = paramType.split("\\[\\]")[0];
5080 paramTypeRet = checkAndGetCplusType(type) + "[]";
5081 } else if (paramType.contains("vector")) {
5082 // Just return it as is if it's not an array
5083 String type = paramType.split("<")[1].split(">")[0];
5084 paramTypeRet = checkAndGetCplusType(type) + "[]";
5086 paramTypeRet = paramType;
5088 return paramTypeRet;
5092 // Detect array declaration, e.g. int A[],
5093 // then generate "int A[]" in C++ as "vector<int> A"
5094 // This method just returns the type
5095 private String checkAndGetCplusArrayType(String paramType, String param) {
5097 String paramTypeRet = null;
5098 // Check for array declaration
5099 if (param.contains("[]")) {
5100 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5101 } else if (paramType.contains("vector")) {
5102 // Just return it as is if it's not an array
5103 String type = paramType.split("<")[1].split(">")[0];
5104 paramTypeRet = checkAndGetCplusType(type) + "[]";
5106 paramTypeRet = paramType;
5108 return paramTypeRet;
5112 // Return the class type for class resolution (for return value)
5113 // - Check and return C++ array class, e.g. int A[] into int*
5114 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5115 private String checkAndGetCplusRetClsType(String paramType) {
5117 String paramTypeRet = null;
5118 // Check for array declaration
5119 if (paramType.contains("[]")) {
5120 String type = paramType.split("\\[\\]")[0];
5121 paramTypeRet = getSimpleArrayType(type) + "*";
5122 } else if (paramType.contains("<") && paramType.contains(">")) {
5123 // Just return it as is if it's not an array
5124 String type = paramType.split("<")[1].split(">")[0];
5125 paramTypeRet = "vector<" + getGenericType(type) + ">";
5127 paramTypeRet = paramType;
5129 return paramTypeRet;
5133 // Return the class type for class resolution (for method arguments)
5134 // - Check and return C++ array class, e.g. int A[] into int*
5135 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5136 private String checkAndGetCplusArgClsType(String paramType, String param) {
5138 String paramTypeRet = getEnumCplusClsType(paramType);
5139 if (!paramTypeRet.equals(paramType))
5140 // Just return if it is an enum type
5141 // Type will still be the same if it's not an enum type
5142 return paramTypeRet;
5144 // Check for array declaration
5145 if (param.contains("[]")) {
5146 paramTypeRet = getSimpleArrayType(paramType) + "*";
5147 } else if (paramType.contains("<") && paramType.contains(">")) {
5148 // Just return it as is if it's not an array
5149 String type = paramType.split("<")[1].split(">")[0];
5150 paramTypeRet = "vector<" + getGenericType(type) + ">";
5152 paramTypeRet = paramType;
5154 return paramTypeRet;
5158 // Detect array declaration, e.g. int A[],
5159 // then generate type "int[]"
5160 private String checkAndGetArray(String paramType, String param) {
5162 String paramTypeRet = null;
5163 // Check for array declaration
5164 if (param.contains("[]")) {
5165 paramTypeRet = paramType + "[]";
5167 // Just return it as is if it's not an array
5168 paramTypeRet = paramType;
5170 return paramTypeRet;
5174 // Is array or list?
5175 private boolean isArrayOrList(String paramType, String param) {
5177 // Check for array declaration
5180 else if (isList(paramType))
5188 // For return type we use retType as input parameter
5189 private boolean isArray(String param) {
5191 // Check for array declaration
5192 if (param.contains("[]"))
5200 private boolean isList(String paramType) {
5202 // Check for array declaration
5203 if (paramType.contains("List"))
5210 // Get the right type for a callback object
5211 private String checkAndGetParamClass(String paramType) {
5213 // Check if this is generics
5214 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5215 return exchangeParamType(paramType);
5216 } else if (isList(paramType) &&
5217 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5218 return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5224 // Returns the other interface for type-checking purposes for USERDEFINED
5225 // classes based on the information provided in multiple policy files
5226 // e.g. return CameraWithXXX instead of Camera
5227 private String exchangeParamType(String intface) {
5229 // Param type that's passed is the interface name we need to look for
5230 // in the map of interfaces, based on available policy files.
5231 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5232 if (decHandler != null) {
5233 // We've found the required interface policy files
5234 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5235 Set<String> setExchInt = reqDecl.getInterfaces();
5236 if (setExchInt.size() == 1) {
5237 Iterator iter = setExchInt.iterator();
5238 return (String) iter.next();
5240 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5241 ". Only one new interface can be declared if the object " + intface +
5242 " needs to be passed in as an input parameter!\n");
5245 // NULL value - this means policy files missing
5246 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5247 "... Please provide the necessary policy files for user-defined types." +
5248 " If this is an array please type the brackets after the variable name," +
5249 " e.g. \"String str[]\", not \"String[] str\"." +
5250 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5251 " supports List/ArrayList (Java) or list (C++).\n");
5256 public static void main(String[] args) throws Exception {
5258 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5259 if ((args.length == 0 ||
5260 args[0].equals("-help") ||
5261 args[0].equals("--help")||
5262 args[0].equals("-h"))) {
5264 IoTCompiler.printUsage();
5266 } else if (args.length > 1) {
5268 IoTCompiler comp = new IoTCompiler();
5270 //boolean driverDefined = false;
5271 boolean controllerDefined = false;
5273 if (!controllerDefined && args[i].equals("-cont")) {
5274 comp.setControllerClass(args[i+1]);
5275 controllerDefined = true;
5278 // Parse main policy file
5279 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5280 // Parse "requires" policy file
5281 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5282 // Get interface name
5283 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5284 comp.setDataStructures(intface, pnPol, pnReq);
5285 comp.getMethodsForIntface(intface);
5287 if (args[i].equals("-drv")) {
5288 comp.setDriverClass(intface, args[i+1]);
5291 throw new Error("IoTCompiler: ERROR - driver class name is needed for the interface: " + intface + "\n");
5292 // 1) Check if this is the last option before "-java" or "-cplus"
5293 // 2) Check if this is really the last option
5294 } while(!args[i].equals("-java") &&
5295 !args[i].equals("-cplus") &&
5297 // Controller class name needs to be defined at least once
5298 if (!controllerDefined)
5299 throw new Error("IoTCompiler: ERROR - controller class name has not been specified!\n");
5301 // Generate everything if we don't see "-java" or "-cplus"
5302 if (i == args.length) {
5303 comp.generateEnumJava();
5304 comp.generateStructJava();
5305 comp.generateJavaLocalInterfaces();
5306 comp.generateJavaInterfaces();
5307 comp.generateJavaStubClasses();
5308 comp.generateJavaSkeletonClass();
5309 comp.generateEnumCplus();
5310 comp.generateStructCplus();
5311 comp.generateCplusLocalInterfaces();
5312 comp.generateCPlusInterfaces();
5313 comp.generateCPlusStubClassesHpp();
5314 comp.generateCPlusStubClassesCpp();
5315 comp.generateCplusSkeletonClassHpp();
5316 comp.generateCplusSkeletonClassCpp();
5318 // Check other options
5319 while(i < args.length) {
5321 if (!args[i].equals("-java") &&
5322 !args[i].equals("-cplus")) {
5323 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5325 if (i + 1 < args.length) {
5326 comp.setDirectory(args[i+1]);
5328 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5330 if (args[i].equals("-java")) {
5331 comp.generateEnumJava();
5332 comp.generateStructJava();
5333 comp.generateJavaLocalInterfaces();
5334 comp.generateJavaInterfaces();
5335 comp.generateJavaStubClasses();
5336 comp.generateJavaSkeletonClass();
5338 comp.generateEnumCplus();
5339 comp.generateStructCplus();
5340 comp.generateCplusLocalInterfaces();
5341 comp.generateCPlusInterfaces();
5342 comp.generateCPlusStubClassesHpp();
5343 comp.generateCPlusStubClassesCpp();
5344 comp.generateCplusSkeletonClassHpp();
5345 comp.generateCplusSkeletonClassCpp();
5352 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5353 IoTCompiler.printUsage();
5354 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");