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 // Data structure to store our types (primitives and non-primitives) for compilation
52 private Map<String,String> mapPrimitives;
53 private Map<String,String> mapNonPrimitivesJava;
54 private Map<String,String> mapNonPrimitivesCplus;
55 // Other data structures
56 private Map<String,Integer> mapIntfaceObjId; // Maps interface name to object Id
57 private Map<String,Integer> mapNewIntfaceObjId; // Maps new interface name to its object Id (keep track of stubs)
58 private PrintWriter pw;
60 private String subdir;
66 private final static String OUTPUT_DIRECTORY = "output_files";
68 private enum ParamCategory {
70 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
71 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
73 STRUCT, // Struct type
74 USERDEFINED // Assumed as driver classes
81 public IoTCompiler() {
83 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
84 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
85 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
86 mapIntfaceObjId = new HashMap<String,Integer>();
87 mapNewIntfaceObjId = new HashMap<String,Integer>();
88 mapPrimitives = new HashMap<String,String>();
89 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
90 mapNonPrimitivesJava = new HashMap<String,String>();
91 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
92 mapNonPrimitivesCplus = new HashMap<String,String>();
93 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
95 dir = OUTPUT_DIRECTORY;
101 * setDataStructures() sets parse tree and other data structures based on policy files.
103 * It also generates parse tree (ParseTreeHandler) and
104 * copies useful information from parse tree into
105 * InterfaceDecl, CapabilityDecl, and RequiresDecl
107 * Additionally, the data structure handles are
108 * returned from tree-parsing for further process.
110 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
112 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
113 DeclarationHandler decHandler = new DeclarationHandler();
114 // Process ParseNode and generate Declaration objects
116 ptHandler.processInterfaceDecl();
117 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
118 decHandler.addInterfaceDecl(origInt, intDecl);
120 ptHandler.processCapabilityDecl();
121 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
122 decHandler.addCapabilityDecl(origInt, capDecl);
124 ptHandler.processRequiresDecl();
125 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
126 decHandler.addRequiresDecl(origInt, reqDecl);
128 ptHandler.processEnumDecl();
129 EnumDecl enumDecl = ptHandler.getEnumDecl();
130 decHandler.addEnumDecl(origInt, enumDecl);
132 ptHandler.processStructDecl();
133 StructDecl structDecl = ptHandler.getStructDecl();
134 decHandler.addStructDecl(origInt, structDecl);
136 mapIntfacePTH.put(origInt, ptHandler);
137 mapIntDeclHand.put(origInt, decHandler);
138 // Set object Id counter to 0 for each interface
139 mapIntfaceObjId.put(origInt, new Integer(0));
144 * getMethodsForIntface() reads for methods in the data structure
146 * It is going to give list of methods for a certain interface
147 * based on the declaration of capabilities.
149 public void getMethodsForIntface(String origInt) {
151 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
152 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
153 // Get set of new interfaces, e.g. CameraWithCaptureAndData
154 // Generate this new interface with all the methods it needs
155 // from different capabilities it declares
156 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
157 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
158 Set<String> setIntfaces = reqDecl.getInterfaces();
159 for (String strInt : setIntfaces) {
161 // Initialize a set of methods
162 Set<String> setMethods = new HashSet<String>();
163 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
164 List<String> listCapab = reqDecl.getCapabList(strInt);
165 for (String strCap : listCapab) {
167 // Get list of methods for each capability
168 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
169 List<String> listCapabMeth = capDecl.getMethods(strCap);
170 for (String strMeth : listCapabMeth) {
172 // Add methods into setMethods
173 // This is to also handle redundancies (say two capabilities
174 // share the same methods)
175 setMethods.add(strMeth);
178 // Add interface and methods information into map
179 mapNewIntMethods.put(strInt, setMethods);
181 // Map the map of interface-methods to the original interface
182 mapInt2NewInts.put(origInt, mapNewIntMethods);
187 * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
189 private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
191 for (String method : methods) {
193 List<String> methParams = intDecl.getMethodParams(method);
194 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
195 print("public " + intDecl.getMethodType(method) + " " +
196 intDecl.getMethodId(method) + "(");
197 for (int i = 0; i < methParams.size(); i++) {
198 // Check for params with driver class types and exchange it
199 // with its remote interface
200 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
201 print(paramType + " " + methParams.get(i));
202 // Check if this is the last element (don't print a comma)
203 if (i != methParams.size() - 1) {
213 * HELPER: writeMethodJavaInterface() writes the method of the interface
215 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
217 for (String method : methods) {
219 List<String> methParams = intDecl.getMethodParams(method);
220 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
221 print("public " + intDecl.getMethodType(method) + " " +
222 intDecl.getMethodId(method) + "(");
223 for (int i = 0; i < methParams.size(); i++) {
224 // Check for params with driver class types and exchange it
225 // with its remote interface
226 String paramType = methPrmTypes.get(i);
227 print(paramType + " " + methParams.get(i));
228 // Check if this is the last element (don't print a comma)
229 if (i != methParams.size() - 1) {
239 * HELPER: generateEnumJava() writes the enumeration declaration
241 private void generateEnumJava() throws IOException {
243 // Create a new directory
244 createDirectory(dir);
245 for (String intface : mapIntfacePTH.keySet()) {
246 // Get the right EnumDecl
247 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
248 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
249 Set<String> enumTypes = enumDecl.getEnumDeclarations();
250 // Iterate over enum declarations
251 for (String enType : enumTypes) {
252 // Open a new file to write into
253 FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
254 pw = new PrintWriter(new BufferedWriter(fw));
255 println("public enum " + enType + " {");
256 List<String> enumMembers = enumDecl.getMembers(enType);
257 for (int i = 0; i < enumMembers.size(); i++) {
259 String member = enumMembers.get(i);
261 // Check if this is the last element (don't print a comma)
262 if (i != enumMembers.size() - 1)
269 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
276 * HELPER: generateStructJava() writes the struct declaration
278 private void generateStructJava() throws IOException {
280 // Create a new directory
281 createDirectory(dir);
282 for (String intface : mapIntfacePTH.keySet()) {
283 // Get the right StructDecl
284 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
285 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
286 List<String> structTypes = structDecl.getStructTypes();
287 // Iterate over enum declarations
288 for (String stType : structTypes) {
289 // Open a new file to write into
290 FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
291 pw = new PrintWriter(new BufferedWriter(fw));
292 println("public class " + stType + " {");
293 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
294 List<String> structMembers = structDecl.getMembers(stType);
295 for (int i = 0; i < structMembers.size(); i++) {
297 String memberType = structMemberTypes.get(i);
298 String member = structMembers.get(i);
299 println("public static " + memberType + " " + member + ";");
303 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
310 * generateJavaLocalInterface() writes the local interface and provides type-checking.
312 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
313 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
314 * The local interface has to be the input parameter for the stub and the stub
315 * interface has to be the input parameter for the local class.
317 public void generateJavaLocalInterfaces() throws IOException {
319 // Create a new directory
320 createDirectory(dir);
321 for (String intface : mapIntfacePTH.keySet()) {
322 // Open a new file to write into
323 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
324 pw = new PrintWriter(new BufferedWriter(fw));
325 // Pass in set of methods and get import classes
326 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
327 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
328 List<String> methods = intDecl.getMethods();
329 Set<String> importClasses = getImportClasses(methods, intDecl);
330 printImportStatements(importClasses);
331 // Write interface header
333 println("public interface " + intface + " {");
335 writeMethodJavaLocalInterface(methods, intDecl);
338 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
344 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
346 public void generateJavaInterfaces() throws IOException {
348 // Create a new directory
349 String path = createDirectories(dir, subdir);
350 for (String intface : mapIntfacePTH.keySet()) {
352 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
353 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
355 // Open a new file to write into
356 String newIntface = intMeth.getKey();
357 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
358 pw = new PrintWriter(new BufferedWriter(fw));
359 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
360 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
361 // Pass in set of methods and get import classes
362 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
363 printImportStatements(importClasses);
364 // Write interface header
366 println("public interface " + newIntface + " {\n");
368 writeMethodJavaInterface(intMeth.getValue(), intDecl);
371 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
378 * HELPER: writePropertiesJavaPermission() writes the permission in properties
380 private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
382 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
383 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
384 String newIntface = intMeth.getKey();
385 int newObjectId = mapNewIntfaceObjId.get(newIntface);
386 println("private final static int object" + newObjectId + "Id = " +
387 newObjectId + ";\t//" + newIntface);
388 Set<String> methodIds = intMeth.getValue();
389 print("private static Integer[] object" + newObjectId + "Permission = { ");
391 for (String methodId : methodIds) {
392 int methodNumId = intDecl.getMethodNumId(methodId);
393 print(Integer.toString(methodNumId));
394 // Check if this is the last element (don't print a comma)
395 if (i != methodIds.size() - 1) {
401 println("private List<Integer> set" + newObjectId + "Allowed;");
407 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
409 private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
411 println("private IoTRMICall rmiCall;");
412 println("private String address;");
413 println("private int[] ports;\n");
415 Integer objId = mapIntfaceObjId.get(intface);
416 println("private final static int objectId = " + objId + ";");
417 mapNewIntfaceObjId.put(newIntface, objId);
418 mapIntfaceObjId.put(intface, objId++);
420 // We assume that each class only has one callback interface for now
421 Iterator it = callbackClasses.iterator();
422 String callbackType = (String) it.next();
423 println("// Callback properties");
424 println("private IoTRMIObject rmiObj;");
425 println("List<" + callbackType + "> listCallbackObj;");
426 println("private static int objIdCnt = 0;");
427 // Generate permission stuff for callback stubs
428 DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
429 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
430 writePropertiesJavaPermission(callbackType, intDecl);
437 * HELPER: writeConstructorJavaPermission() writes the permission in constructor
439 private void writeConstructorJavaPermission(String intface) {
441 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
442 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
443 String newIntface = intMeth.getKey();
444 int newObjectId = mapNewIntfaceObjId.get(newIntface);
445 println("set" + newObjectId + "Allowed = Arrays.asList(object" + newObjectId +"Permission);");
451 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
453 private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
455 println("public " + newStubClass + "(int _port, String _address, int _rev, int[] _ports) throws Exception {");
456 println("address = _address;");
457 println("ports = _ports;");
458 println("rmiCall = new IoTRMICall(_port, _address, _rev);");
460 Iterator it = callbackClasses.iterator();
461 String callbackType = (String) it.next();
462 writeConstructorJavaPermission(intface);
463 println("listCallbackObj = new ArrayList<" + callbackType + ">();");
464 println("___initCallBack();");
471 * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
473 private void writeJavaMethodCallbackPermission(String intface) {
475 println("int methodId = IoTRMIObject.getMethodId(method);");
476 // Get all the different stubs
477 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
478 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
479 String newIntface = intMeth.getKey();
480 int newObjectId = mapNewIntfaceObjId.get(newIntface);
481 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
482 println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
489 * HELPER: writeInitCallbackJavaStub() writes callback initialization in stub
491 private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl) {
493 println("public void ___initCallBack() {");
494 // Generate main thread for callbacks
495 println("Thread thread = new Thread() {");
496 println("public void run() {");
498 println("rmiObj = new IoTRMIObject(ports[0]);");
499 println("while (true) {");
500 println("byte[] method = rmiObj.getMethodBytes();");
501 writeJavaMethodCallbackPermission(intface);
502 println("int objId = IoTRMIObject.getObjectId(method);");
503 println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);");
504 println("if (skel != null) {");
505 println("skel.invokeMethod(rmiObj);");
507 println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");");
510 println("} catch (Exception ex) {");
511 println("ex.printStackTrace();");
512 println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");");
516 println("thread.start();\n");
517 // Generate info sending part
518 String method = "___initCallBack()";
519 println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";");
520 println("Class<?> retType = void.class;");
521 println("Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };");
522 println("Object[] paramObj = new Object[] { ports[0], address, 0 };");
523 println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
529 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
531 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
533 // Iterate and find enum declarations
534 for (int i = 0; i < methParams.size(); i++) {
535 String paramType = methPrmTypes.get(i);
536 String param = methParams.get(i);
537 String simpleType = getSimpleType(paramType);
538 if (isEnumClass(simpleType)) {
539 // Check if this is enum type
540 if (isArray(param)) { // An array
541 println("int len" + i + " = " + param + ".length;");
542 println("int paramEnum" + i + "[] = new int[len];");
543 println("for (int i = 0; i < len" + i + "; i++) {");
544 println("paramEnum" + i + "[i] = " + param + "[i].ordinal();");
546 } else if (isList(paramType)) { // A list
547 println("int len" + i + " = " + param + ".size();");
548 println("int paramEnum" + i + "[] = new int[len];");
549 println("for (int i = 0; i < len" + i + "; i++) {");
550 println("paramEnum" + i + "[i] = " + param + ".get(i).ordinal();");
552 } else { // Just one element
553 println("int paramEnum" + i + "[] = new int[1];");
554 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
562 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
564 private void checkAndWriteEnumRetTypeJavaStub(String retType) {
566 // Strips off array "[]" for return type
567 String pureType = getSimpleArrayType(getSimpleType(retType));
568 // Take the inner type of generic
569 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
570 pureType = getTypeOfGeneric(retType)[0];
571 if (isEnumClass(pureType)) {
572 // Check if this is enum type
574 println("int[] retEnum = (int[]) retObj;");
575 println(pureType + "[] enumVals = " + pureType + ".values();");
576 if (isArray(retType)) { // An array
577 println("int retLen = retEnum.length;");
578 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
579 println("for (int i = 0; i < retLen; i++) {");
580 println("enumRetVal[i] = enumVals[retEnum[i]];");
582 } else if (isList(retType)) { // A list
583 println("int retLen = retEnum.length;");
584 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
585 println("for (int i = 0; i < retLen; i++) {");
586 println("enumRetVal.add(enumVals[retEnum[i]]);");
588 } else { // Just one element
589 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
591 println("return enumRetVal;");
597 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
599 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
600 InterfaceDecl intDecl, String method) {
602 // Iterate and find struct declarations
603 for (int i = 0; i < methParams.size(); i++) {
604 String paramType = methPrmTypes.get(i);
605 String param = methParams.get(i);
606 String simpleType = getSimpleType(paramType);
607 if (isStructClass(simpleType)) {
608 // Check if this is enum type
609 int methodNumId = intDecl.getMethodNumId(method);
610 String helperMethod = methodNumId + "struct" + i;
611 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
612 println("Class<?> retTypeStruct" + i + " = void.class;");
613 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
614 if (isArray(param)) { // An array
615 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
616 } else if (isList(paramType)) { // A list
617 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
618 } else { // Just one element
619 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
621 println("rmiCall.remoteCall(objectId, methodIdStruct" + i +
622 ", retTypeStruct" + i + ", null, paramClsStruct" + i +
623 ", paramObjStruct" + i + ");\n");
630 * HELPER: isStructPresent() checks presence of struct
632 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
634 // Iterate and find enum declarations
635 for (int i = 0; i < methParams.size(); i++) {
636 String paramType = methPrmTypes.get(i);
637 String param = methParams.get(i);
638 String simpleType = getSimpleType(paramType);
639 if (isStructClass(simpleType))
647 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
649 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
651 // Iterate and find struct declarations - count number of params
652 for (int i = 0; i < methParams.size(); i++) {
653 String paramType = methPrmTypes.get(i);
654 String param = methParams.get(i);
655 String simpleType = getGenericType(paramType);
656 if (isStructClass(simpleType)) {
657 int members = getNumOfMembers(simpleType);
658 if (isArray(param)) { // An array
659 String structLen = param + ".length";
660 print(members + "*" + structLen);
661 } else if (isList(paramType)) { // A list
662 String structLen = param + ".size()";
663 print(members + "*" + structLen);
665 print(Integer.toString(members));
668 if (i != methParams.size() - 1) {
676 * HELPER: writeStructMembersJavaStub() writes parameters of struct
678 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
680 // Get the struct declaration for this struct and generate initialization code
681 StructDecl structDecl = getStructDecl(simpleType);
682 List<String> memTypes = structDecl.getMemberTypes(simpleType);
683 List<String> members = structDecl.getMembers(simpleType);
684 if (isArray(param)) { // An array
685 println("for(int i = 0; i < " + param + ".length; i++) {");
686 } else if (isList(paramType)) { // A list
687 println("for(int i = 0; i < " + param + ".size(); i++) {");
689 if (isArrayOrList(param, paramType)) { // An array or list
690 for (int i = 0; i < members.size(); i++) {
691 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
692 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
693 print("paramObj[pos++] = " + param + "[i].");
694 print(getSimpleIdentifier(members.get(i)));
698 } else { // Just one struct element
699 for (int i = 0; i < members.size(); i++) {
700 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
701 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
702 print("paramObj[pos++] = " + param + ".");
703 print(getSimpleIdentifier(members.get(i)));
711 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
713 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
715 print("int paramLen = ");
716 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
718 println("Object[] paramObj = new Object[paramLen];");
719 println("Class<?>[] paramCls = new Class<?>[paramLen];");
720 println("int pos = 0;");
721 // Iterate again over the parameters
722 for (int i = 0; i < methParams.size(); i++) {
723 String paramType = methPrmTypes.get(i);
724 String param = methParams.get(i);
725 String simpleType = getGenericType(paramType);
726 if (isStructClass(simpleType)) {
727 writeStructMembersJavaStub(simpleType, paramType, param);
729 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
730 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
731 print("paramObj[pos++] = ");
732 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
741 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
743 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
745 // Get the struct declaration for this struct and generate initialization code
746 StructDecl structDecl = getStructDecl(simpleType);
747 List<String> memTypes = structDecl.getMemberTypes(simpleType);
748 List<String> members = structDecl.getMembers(simpleType);
749 if (isArrayOrList(retType, retType)) { // An array or list
750 println("for(int i = 0; i < retLen; i++) {");
752 if (isArray(retType)) { // An array
753 for (int i = 0; i < members.size(); i++) {
754 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
755 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
756 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
759 } else if (isList(retType)) { // A list
760 println(simpleType + " structRetMem = new " + simpleType + "();");
761 for (int i = 0; i < members.size(); i++) {
762 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
763 print("structRetMem." + getSimpleIdentifier(members.get(i)));
764 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
766 println("structRet.add(structRetMem);");
768 } else { // Just one struct element
769 for (int i = 0; i < members.size(); i++) {
770 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
771 print("structRet." + getSimpleIdentifier(members.get(i)));
772 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
775 println("return structRet;");
780 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
782 private void writeStructReturnJavaStub(String simpleType, String retType) {
784 // Handle the returned struct!!!
785 println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
786 // Minimum retLen is 1 if this is a single struct object
787 println("int retLen = (int) retLenObj;");
788 int numMem = getNumOfMembers(simpleType);
789 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
790 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
791 println("int retPos = 0;");
792 // Get the struct declaration for this struct and generate initialization code
793 StructDecl structDecl = getStructDecl(simpleType);
794 List<String> memTypes = structDecl.getMemberTypes(simpleType);
795 List<String> members = structDecl.getMembers(simpleType);
796 if (isArrayOrList(retType, retType)) { // An array or list
797 println("for(int i = 0; i < retLen; i++) {");
798 for (int i = 0; i < members.size(); i++) {
799 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
800 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
801 println("retClsVal[retPos++] = null;");
804 } else { // Just one struct element
805 for (int i = 0; i < members.size(); i++) {
806 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
807 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
808 println("retClsVal[retPos++] = null;");
811 println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);");
812 if (isArray(retType)) { // An array
813 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
814 println("for(int i = 0; i < retLen; i++) {");
815 println("structRet[i] = new " + simpleType + "();");
817 } else if (isList(retType)) { // A list
818 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
820 println(simpleType + " structRet = new " + simpleType + "();");
821 println("int retObjPos = 0;");
822 writeStructRetMembersJavaStub(simpleType, retType);
827 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
829 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
830 List<String> methPrmTypes, String method) {
832 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
833 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
834 String retType = intDecl.getMethodType(method);
835 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
836 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
837 // Generate array of parameter types
838 if (isStructPresent(methParams, methPrmTypes)) {
839 writeStructParamClassJavaStub(methParams, methPrmTypes);
841 print("Class<?>[] paramCls = new Class<?>[] { ");
842 for (int i = 0; i < methParams.size(); i++) {
843 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
844 print(getSimpleType(getEnumType(paramType)) + ".class");
845 // Check if this is the last element (don't print a comma)
846 if (i != methParams.size() - 1) {
851 // Generate array of parameter objects
852 print("Object[] paramObj = new Object[] { ");
853 for (int i = 0; i < methParams.size(); i++) {
854 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
855 // Check if this is the last element (don't print a comma)
856 if (i != methParams.size() - 1) {
862 // Check if this is "void"
863 if (retType.equals("void")) {
864 println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
865 } else { // We do have a return value
866 // Generate array of parameter types
867 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
868 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType);
870 // Check if the return value NONPRIMITIVES
871 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
872 String[] retGenValType = getTypeOfGeneric(retType);
873 println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
874 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
875 println("return (" + retType + ")retObj;");
876 } else if (getParamCategory(retType) == ParamCategory.ENUM) {
877 // This is an enum type
878 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
879 checkAndWriteEnumRetTypeJavaStub(retType);
881 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
882 println("return (" + retType + ")retObj;");
890 * HELPER: returnGenericCallbackType() returns the callback type
892 private String returnGenericCallbackType(String paramType) {
894 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
895 return getTypeOfGeneric(paramType)[0];
902 * HELPER: checkCallbackType() checks the callback type
904 private boolean checkCallbackType(String paramType, String callbackType) {
906 String prmType = returnGenericCallbackType(paramType);
907 return callbackType.equals(prmType);
912 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
914 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
915 List<String> methPrmTypes, String method, String callbackType) {
918 // Check if this is single object, array, or list of objects
919 for (int i = 0; i < methParams.size(); i++) {
920 String paramType = methPrmTypes.get(i);
921 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
922 String param = methParams.get(i);
923 if (isArrayOrList(paramType, param)) { // Generate loop
924 println("for (" + paramType + " cb : " + getSimpleIdentifier(param) + ") {");
925 println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
927 println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(" +
928 getSimpleIdentifier(param) + ", objIdCnt++);");
929 println("listCallbackObj.add(skel);");
930 if (isArrayOrList(paramType, param))
934 println("} catch (Exception ex) {");
935 println("ex.printStackTrace();");
936 println("throw new Error(\"Exception when generating skeleton objects!\");");
938 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
939 String retType = intDecl.getMethodType(method);
940 println("Class<?> retType = " + getSimpleType(getEnumType(retType)) + ".class;");
941 // Generate array of parameter types
942 print("Class<?>[] paramCls = new Class<?>[] { ");
943 for (int i = 0; i < methParams.size(); i++) {
944 String paramType = methPrmTypes.get(i);
945 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
947 } else { // Generate normal classes if it's not a callback object
948 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
949 print(getSimpleType(prmType) + ".class");
951 if (i != methParams.size() - 1) // Check if this is the last element
955 // Generate array of parameter objects
956 print("Object[] paramObj = new Object[] { ");
957 for (int i = 0; i < methParams.size(); i++) {
958 String paramType = methPrmTypes.get(i);
959 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
960 //if (isArray(methPrmTypes.get(i), methParams.get(i)))
961 if (isArray(methParams.get(i)))
962 print(getSimpleIdentifier(methParams.get(i)) + ".length");
963 else if (isList(methPrmTypes.get(i)))
964 print(getSimpleIdentifier(methParams.get(i)) + ".size()");
966 print("new Integer(1)");
968 print(getSimpleIdentifier(methParams.get(i)));
969 if (i != methParams.size() - 1)
973 // Check if this is "void"
974 if (retType.equals("void")) {
975 println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
976 } else { // We do have a return value
977 // Check if the return value NONPRIMITIVES
978 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
979 String[] retGenValType = getTypeOfGeneric(retType);
980 println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
981 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
982 println("return (" + retType + ")retObj;");
984 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
985 println("return (" + retType + ")retObj;");
992 * HELPER: writeMethodJavaStub() writes the methods of the stub class
994 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
996 for (String method : methods) {
998 List<String> methParams = intDecl.getMethodParams(method);
999 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1000 print("public " + intDecl.getMethodType(method) + " " +
1001 intDecl.getMethodId(method) + "(");
1002 boolean isCallbackMethod = false;
1003 String callbackType = null;
1004 for (int i = 0; i < methParams.size(); i++) {
1006 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1007 // Check if this has callback object
1008 if (callbackClasses.contains(paramType)) {
1009 isCallbackMethod = true;
1010 callbackType = paramType;
1011 // Even if there're 2 callback arguments, we expect them to be of the same interface
1013 print(methPrmTypes.get(i) + " " + methParams.get(i));
1014 // Check if this is the last element (don't print a comma)
1015 if (i != methParams.size() - 1) {
1020 // Now, write the body of stub!
1021 if (isCallbackMethod)
1022 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1024 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method);
1026 // Write the init callback helper method
1027 if (isCallbackMethod)
1028 writeInitCallbackJavaStub(callbackType, intDecl);
1034 * generateJavaStubClasses() generate stubs based on the methods list in Java
1036 public void generateJavaStubClasses() throws IOException {
1038 // Create a new directory
1039 String path = createDirectories(dir, subdir);
1040 for (String intface : mapIntfacePTH.keySet()) {
1042 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1043 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1045 // Open a new file to write into
1046 String newIntface = intMeth.getKey();
1047 String newStubClass = newIntface + "_Stub";
1048 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1049 pw = new PrintWriter(new BufferedWriter(fw));
1050 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1051 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1052 // Pass in set of methods and get import classes
1053 Set<String> methods = intMeth.getValue();
1054 Set<String> importClasses = getImportClasses(methods, intDecl);
1055 List<String> stdImportClasses = getStandardJavaImportClasses();
1056 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1057 printImportStatements(allImportClasses); println("");
1058 // Find out if there are callback objects
1059 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1060 boolean callbackExist = !callbackClasses.isEmpty();
1061 // Write class header
1062 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1064 writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses);
1065 // Write constructor
1066 writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses);
1068 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
1071 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1078 * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class
1080 private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
1082 println("private IoTRMICall rmiCall;");
1083 println("private String address;");
1084 println("private int[] ports;\n");
1085 // Get the object Id
1086 println("private static int objectId = 0;");
1087 if (callbackExist) {
1088 // We assume that each class only has one callback interface for now
1089 Iterator it = callbackClasses.iterator();
1090 String callbackType = (String) it.next();
1091 println("// Callback properties");
1092 println("private IoTRMIObject rmiObj;");
1093 println("List<" + callbackType + "> listCallbackObj;");
1094 println("private static int objIdCnt = 0;");
1095 // Generate permission stuff for callback stubs
1096 DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
1097 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
1098 writePropertiesJavaPermission(callbackType, intDecl);
1105 * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class
1107 private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1109 // TODO: If we want callback in callback, then we need to add address and port initializations
1110 println("public " + newStubClass + "(IoTRMICall _rmiCall, int _objectId) throws Exception {");
1111 println("objectId = _objectId;");
1112 println("rmiCall = _rmiCall;");
1113 if (callbackExist) {
1114 Iterator it = callbackClasses.iterator();
1115 String callbackType = (String) it.next();
1116 writeConstructorJavaPermission(intface);
1117 println("listCallbackObj = new ArrayList<" + callbackType + ">();");
1118 println("___initCallBack();");
1119 println("// TODO: Add address and port initialization here if we want callback in callback!");
1126 * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java
1128 * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input
1129 * because all these stubs are populated by the class that takes in this object as a callback
1130 * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects.
1132 public void generateJavaCallbackStubClasses() throws IOException {
1134 // Create a new directory
1135 String path = createDirectories(dir, subdir);
1136 for (String intface : mapIntfacePTH.keySet()) {
1138 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1139 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1141 // Open a new file to write into
1142 String newIntface = intMeth.getKey();
1143 String newStubClass = newIntface + "_CallbackStub";
1144 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1145 pw = new PrintWriter(new BufferedWriter(fw));
1146 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1147 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1148 // Pass in set of methods and get import classes
1149 Set<String> methods = intMeth.getValue();
1150 Set<String> importClasses = getImportClasses(methods, intDecl);
1151 List<String> stdImportClasses = getStandardJavaImportClasses();
1152 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1153 printImportStatements(allImportClasses); println("");
1154 // Find out if there are callback objects
1155 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1156 boolean callbackExist = !callbackClasses.isEmpty();
1157 // Write class header
1158 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1160 writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses);
1161 // Write constructor
1162 writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses);
1164 // TODO: perhaps need to generate callback for callback
1165 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
1168 System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java...");
1175 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1177 private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) {
1179 println("private " + intface + " mainObj;");
1180 //println("private int ports;");
1181 println("private IoTRMIObject rmiObj;\n");
1183 if (callbackExist) {
1184 println("private static int objIdCnt = 0;");
1185 println("private IoTRMICall rmiCall;");
1187 writePropertiesJavaPermission(intface, intDecl);
1193 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1195 private void writeConstructorJavaSkeleton(String newSkelClass, String intface) {
1197 println("public " + newSkelClass + "(" + intface + " _mainObj, int _port) throws Exception {");
1198 println("mainObj = _mainObj;");
1199 println("rmiObj = new IoTRMIObject(_port);");
1200 // Generate permission control initialization
1201 writeConstructorJavaPermission(intface);
1202 println("___waitRequestInvokeMethod();");
1208 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1210 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1212 if (methodType.equals("void"))
1213 print("mainObj." + methodId + "(");
1215 print("return mainObj." + methodId + "(");
1216 for (int i = 0; i < methParams.size(); i++) {
1218 print(getSimpleIdentifier(methParams.get(i)));
1219 // Check if this is the last element (don't print a comma)
1220 if (i != methParams.size() - 1) {
1229 * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class
1231 private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton) {
1233 // This is a callback skeleton generation
1234 if (callbackSkeleton)
1235 println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {");
1237 println("public void ___regCB() throws IOException {");
1238 println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, String.class, int.class },");
1239 println("\tnew Class<?>[] { null, null, null });");
1240 println("rmiCall = new IoTRMICall((int) paramObj[0], (String) paramObj[1], (int) paramObj[2]);");
1246 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1248 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses,
1249 boolean callbackSkeleton) {
1251 for (String method : methods) {
1253 List<String> methParams = intDecl.getMethodParams(method);
1254 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1255 String methodId = intDecl.getMethodId(method);
1256 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1257 boolean isCallbackMethod = false;
1258 String callbackType = null;
1259 for (int i = 0; i < methParams.size(); i++) {
1261 String origParamType = methPrmTypes.get(i);
1262 String paramType = checkAndGetParamClass(origParamType);
1263 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
1264 isCallbackMethod = true;
1265 callbackType = origParamType;
1267 print(paramType + " " + methParams.get(i));
1268 // Check if this is the last element (don't print a comma)
1269 if (i != methParams.size() - 1) {
1274 // Now, write the body of skeleton!
1275 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1277 if (isCallbackMethod)
1278 writeInitCallbackJavaSkeleton(callbackSkeleton);
1284 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1286 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1287 String callbackType) {
1289 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1290 // Iterate over callback objects
1291 for (int i = 0; i < methParams.size(); i++) {
1292 String paramType = methPrmTypes.get(i);
1293 String param = methParams.get(i);
1294 //if (callbackType.equals(paramType)) {
1295 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1297 String exchParamType = checkAndGetParamClass(paramType);
1298 // Print array if this is array or list if this is a list of callback objects
1299 if (isArray(param)) {
1300 println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1301 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1302 } else if (isList(paramType)) {
1303 println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1304 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1306 println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1307 println("objIdCnt++;");
1310 // Generate a loop if needed
1311 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1312 String exchParamType = checkAndGetParamClass(paramType);
1313 if (isArray(param)) {
1314 println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1315 println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1316 println("objIdCnt++;");
1318 } else if (isList(paramType)) {
1319 println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1320 println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt));");
1321 println("objIdCnt++;");
1324 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1327 return mapStubParam;
1332 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1334 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes) {
1336 // Iterate and find enum declarations
1337 for (int i = 0; i < methParams.size(); i++) {
1338 String paramType = methPrmTypes.get(i);
1339 String param = methParams.get(i);
1340 String simpleType = getSimpleType(paramType);
1341 if (isEnumClass(simpleType)) {
1342 // Check if this is enum type
1343 println("int paramInt" + i + "[] = (int[]) paramObj[" + i + "];");
1344 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1345 if (isArray(param)) { // An array
1346 println("int len" + i + " = paramInt" + i + ".length;");
1347 println(simpleType + "[] paramEnum = new " + simpleType + "[len];");
1348 println("for (int i = 0; i < len" + i + "; i++) {");
1349 println("paramEnum[i] = enumVals[paramInt" + i + "[i]];");
1351 } else if (isList(paramType)) { // A list
1352 println("int len" + i + " = paramInt" + i + ".length;");
1353 println("List<" + simpleType + "> paramEnum = new ArrayList<" + simpleType + ">();");
1354 println("for (int i = 0; i < len" + i + "; i++) {");
1355 println("paramEnum.add(enumVals[paramInt" + i + "[i]]);");
1357 } else { // Just one element
1358 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1366 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1368 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1370 // Strips off array "[]" for return type
1371 String pureType = getSimpleArrayType(getSimpleType(retType));
1372 // Take the inner type of generic
1373 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1374 pureType = getTypeOfGeneric(retType)[0];
1375 if (isEnumClass(pureType)) {
1376 // Check if this is enum type
1378 if (isArray(retType)) { // An array
1379 print(pureType + "[] retEnum = " + methodId + "(");
1380 } else if (isList(retType)) { // A list
1381 print("List<" + pureType + "> retEnum = " + methodId + "(");
1382 } else { // Just one element
1383 print(pureType + " retEnum = " + methodId + "(");
1390 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1392 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1394 // Strips off array "[]" for return type
1395 String pureType = getSimpleArrayType(getSimpleType(retType));
1396 // Take the inner type of generic
1397 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1398 pureType = getTypeOfGeneric(retType)[0];
1399 if (isEnumClass(pureType)) {
1400 // Check if this is enum type
1401 if (isArray(retType)) { // An array
1402 println("int retLen = retEnum.length;");
1403 println("int[] retEnumVal = new int[retLen];");
1404 println("for (int i = 0; i < retLen; i++) {");
1405 println("retEnumVal[i] = retEnum[i].ordinal();");
1407 } else if (isList(retType)) { // A list
1408 println("int retLen = retEnum.size();");
1409 println("List<" + pureType + "> retEnumVal = new ArrayList<" + pureType + ">();");
1410 println("for (int i = 0; i < retLen; i++) {");
1411 println("retEnumVal.add(retEnum[i].ordinal());");
1413 } else { // Just one element
1414 println("int[] retEnumVal = new int[1];");
1415 println("retEnumVal[0] = retEnum.ordinal();");
1417 println("Object retObj = retEnumVal;");
1423 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1425 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1426 String method, InterfaceDecl intDecl) {
1428 // Iterate and find struct declarations - count number of params
1429 for (int i = 0; i < methParams.size(); i++) {
1430 String paramType = methPrmTypes.get(i);
1431 String param = methParams.get(i);
1432 String simpleType = getGenericType(paramType);
1433 if (isStructClass(simpleType)) {
1434 int members = getNumOfMembers(simpleType);
1435 print(Integer.toString(members) + "*");
1436 int methodNumId = intDecl.getMethodNumId(method);
1437 print("struct" + methodNumId + "Size" + i);
1440 if (i != methParams.size() - 1) {
1448 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1450 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1451 String param, String method, InterfaceDecl intDecl, int iVar) {
1453 // Get the struct declaration for this struct and generate initialization code
1454 StructDecl structDecl = getStructDecl(simpleType);
1455 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1456 List<String> members = structDecl.getMembers(simpleType);
1457 if (isArrayOrList(param, paramType)) { // An array or list
1458 int methodNumId = intDecl.getMethodNumId(method);
1459 String counter = "struct" + methodNumId + "Size" + iVar;
1460 println("for(int i = 0; i < " + counter + "; i++) {");
1462 println("int pos = 0;");
1463 if (isArrayOrList(param, paramType)) { // An array or list
1464 println("for(int i = 0; i < retLen; i++) {");
1465 for (int i = 0; i < members.size(); i++) {
1466 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1467 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1468 println("paramClsGen[pos++] = null;");
1471 } else { // Just one struct element
1472 for (int i = 0; i < members.size(); i++) {
1473 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1474 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1475 println("paramClsGen[pos++] = null;");
1482 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1484 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1485 List<String> methPrmTypes, String method) {
1487 for (int i = 0; i < methParams.size(); i++) {
1488 String paramType = methPrmTypes.get(i);
1489 String param = methParams.get(i);
1490 String simpleType = getGenericType(paramType);
1491 if (isStructClass(simpleType)) {
1492 int methodNumId = intDecl.getMethodNumId(method);
1493 String counter = "struct" + methodNumId + "Size" + i;
1495 if (isArray(param)) { // An array
1496 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1497 println("for(int i = 0; i < " + counter + "; i++) {");
1498 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1500 } else if (isList(paramType)) { // A list
1501 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1503 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1504 println("int objPos = 0;");
1505 // Initialize members
1506 StructDecl structDecl = getStructDecl(simpleType);
1507 List<String> members = structDecl.getMembers(simpleType);
1508 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1509 if (isArrayOrList(param, paramType)) { // An array or list
1510 println("for(int i = 0; i < " + counter + "; i++) {");
1512 if (isArray(param)) { // An array
1513 for (int j = 0; j < members.size(); j++) {
1514 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1515 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1516 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1519 } else if (isList(paramType)) { // A list
1520 println(simpleType + " paramStructMem = new " + simpleType + "();");
1521 for (int j = 0; j < members.size(); j++) {
1522 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1523 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1524 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1526 println("paramStruct" + i + ".add(paramStructMem);");
1528 } else { // Just one struct element
1529 for (int j = 0; j < members.size(); j++) {
1530 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1531 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1532 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1536 // Take offsets of parameters
1537 println("int offset" + i +" = objPos;");
1544 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1546 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1548 // Minimum retLen is 1 if this is a single struct object
1549 if (isArray(retType))
1550 println("int retLen = retStruct.length;");
1551 else if (isList(retType))
1552 println("int retLen = retStruct.size();");
1553 else // Just single struct object
1554 println("int retLen = 1;");
1555 println("Object retLenObj = retLen;");
1556 println("rmiObj.sendReturnObj(retLenObj);");
1557 int numMem = getNumOfMembers(simpleType);
1558 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1559 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1560 println("int retPos = 0;");
1561 // Get the struct declaration for this struct and generate initialization code
1562 StructDecl structDecl = getStructDecl(simpleType);
1563 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1564 List<String> members = structDecl.getMembers(simpleType);
1565 if (isArrayOrList(retType, retType)) { // An array or list
1566 println("for(int i = 0; i < retLen; i++) {");
1567 for (int i = 0; i < members.size(); i++) {
1568 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1569 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1570 print("retObj[retPos++] = retStruct[i].");
1571 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1575 } else { // Just one struct element
1576 for (int i = 0; i < members.size(); i++) {
1577 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1578 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1579 print("retObj[retPos++] = retStruct.");
1580 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1589 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1591 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1592 List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType) {
1594 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes);
1595 Map<Integer,String> mapStubParam = null;
1596 if (isCallbackMethod)
1597 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType);
1598 // Check if this is "void"
1599 String retType = intDecl.getMethodType(method);
1600 if (retType.equals("void")) {
1601 print(intDecl.getMethodId(method) + "(");
1602 } else if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type
1603 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1604 } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type
1605 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1606 } else { // We do have a return value
1607 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1609 for (int i = 0; i < methParams.size(); i++) {
1611 if (isCallbackMethod) {
1612 print(mapStubParam.get(i)); // Get the callback parameter
1613 } else if (isEnumClass(getSimpleType(methPrmTypes.get(i)))) { // Enum class
1614 print(getEnumParam(methPrmTypes.get(i), methParams.get(i), i));
1615 } else if (isStructClass(getSimpleType(methPrmTypes.get(i)))) {
1616 print("paramStruct" + i);
1618 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1619 print("(" + prmType + ") paramObj[offset" + i + "]");
1621 if (i != methParams.size() - 1)
1625 if (!retType.equals("void")) {
1626 if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) { // Enum type
1627 checkAndWriteEnumRetConvJavaSkeleton(retType);
1628 println("rmiObj.sendReturnObj(retObj);");
1629 } else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) { // Struct type
1630 writeStructReturnJavaSkeleton(getSimpleArrayType(getSimpleType(retType)), retType);
1631 println("rmiObj.sendReturnObj(retCls, retObj);");
1633 println("rmiObj.sendReturnObj(retObj);");
1635 if (isCallbackMethod) { // Catch exception if this is callback
1636 println("} catch(Exception ex) {");
1637 println("ex.printStackTrace();");
1638 println("throw new Error(\"Exception from callback object instantiation!\");");
1645 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1647 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1648 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1650 // Generate array of parameter objects
1651 boolean isCallbackMethod = false;
1652 String callbackType = null;
1653 print("int paramLen = ");
1654 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1656 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1657 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1658 // Iterate again over the parameters
1659 for (int i = 0; i < methParams.size(); i++) {
1660 String paramType = methPrmTypes.get(i);
1661 String param = methParams.get(i);
1662 String simpleType = getGenericType(paramType);
1663 if (isStructClass(simpleType)) {
1664 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1666 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1667 if (callbackClasses.contains(prmType)) {
1668 isCallbackMethod = true;
1669 callbackType = prmType;
1670 println("paramCls[pos] = int.class;");
1671 println("paramClsGen[pos++] = null;");
1672 } else { // Generate normal classes if it's not a callback object
1673 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1674 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1675 print("paramClsGen[pos++] = ");
1676 String prmTypeOth = methPrmTypes.get(i);
1677 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1678 println(getTypeOfGeneric(prmType)[0] + ".class;");
1684 println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);");
1685 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1686 // Write the return value part
1687 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType);
1692 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1694 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1695 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1697 // Generate array of parameter objects
1698 boolean isCallbackMethod = false;
1699 String callbackType = null;
1700 print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { ");
1701 for (int i = 0; i < methParams.size(); i++) {
1703 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1704 if (callbackClasses.contains(paramType)) {
1705 isCallbackMethod = true;
1706 callbackType = paramType;
1708 } else { // Generate normal classes if it's not a callback object
1709 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1710 print(getSimpleType(getEnumType(prmType)) + ".class");
1712 if (i != methParams.size() - 1)
1716 // Generate generic class if it's a generic type.. null otherwise
1717 print("new Class<?>[] { ");
1718 for (int i = 0; i < methParams.size(); i++) {
1719 String prmType = methPrmTypes.get(i);
1720 if (getParamCategory(prmType) == ParamCategory.NONPRIMITIVES)
1721 print(getTypeOfGeneric(prmType)[0] + ".class");
1724 if (i != methParams.size() - 1)
1728 // Write the return value part
1729 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType);
1734 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1736 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1738 // Use this set to handle two same methodIds
1739 Set<String> uniqueMethodIds = new HashSet<String>();
1740 for (String method : methods) {
1742 List<String> methParams = intDecl.getMethodParams(method);
1743 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1744 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1745 String methodId = intDecl.getMethodId(method);
1746 print("public void ___");
1747 String helperMethod = methodId;
1748 if (uniqueMethodIds.contains(methodId))
1749 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1751 uniqueMethodIds.add(methodId);
1752 String retType = intDecl.getMethodType(method);
1753 print(helperMethod + "(");
1754 boolean begin = true;
1755 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1756 String paramType = methPrmTypes.get(i);
1757 String param = methParams.get(i);
1758 String simpleType = getSimpleType(paramType);
1759 if (isStructClass(simpleType)) {
1760 if (!begin) { // Generate comma for not the beginning variable
1761 print(", "); begin = false;
1763 int methodNumId = intDecl.getMethodNumId(method);
1764 print("int struct" + methodNumId + "Size" + i);
1767 // Check if this is "void"
1768 if (retType.equals("void"))
1771 println(") throws IOException {");
1772 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1775 String methodId = intDecl.getMethodId(method);
1776 print("public void ___");
1777 String helperMethod = methodId;
1778 if (uniqueMethodIds.contains(methodId))
1779 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1781 uniqueMethodIds.add(methodId);
1782 // Check if this is "void"
1783 String retType = intDecl.getMethodType(method);
1784 if (retType.equals("void"))
1785 println(helperMethod + "() {");
1787 println(helperMethod + "() throws IOException {");
1788 // Now, write the helper body of skeleton!
1789 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1793 // Write method helper for structs
1794 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1799 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1801 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1802 InterfaceDecl intDecl) {
1804 // Use this set to handle two same methodIds
1805 for (String method : methods) {
1807 List<String> methParams = intDecl.getMethodParams(method);
1808 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1809 // Check for params with structs
1810 for (int i = 0; i < methParams.size(); i++) {
1811 String paramType = methPrmTypes.get(i);
1812 String param = methParams.get(i);
1813 String simpleType = getSimpleType(paramType);
1814 if (isStructClass(simpleType)) {
1815 int methodNumId = intDecl.getMethodNumId(method);
1816 print("public int ___");
1817 String helperMethod = methodNumId + "struct" + i;
1818 println(helperMethod + "() {");
1819 // Now, write the helper body of skeleton!
1820 println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1821 println("return (int) paramObj[0];");
1830 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1832 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1833 InterfaceDecl intDecl) {
1835 // Use this set to handle two same methodIds
1836 for (String method : methods) {
1838 List<String> methParams = intDecl.getMethodParams(method);
1839 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1840 // Check for params with structs
1841 for (int i = 0; i < methParams.size(); i++) {
1842 String paramType = methPrmTypes.get(i);
1843 String param = methParams.get(i);
1844 String simpleType = getSimpleType(paramType);
1845 if (isStructClass(simpleType)) {
1846 int methodNumId = intDecl.getMethodNumId(method);
1847 print("public int ___");
1848 String helperMethod = methodNumId + "struct" + i;
1849 println(helperMethod + "(IoTRMIObject rmiObj) {");
1850 // Now, write the helper body of skeleton!
1851 println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1852 println("return (int) paramObj[0];");
1861 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1863 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1865 // Use this set to handle two same methodIds
1866 for (String method : methods) {
1868 List<String> methParams = intDecl.getMethodParams(method);
1869 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1870 // Check for params with structs
1871 for (int i = 0; i < methParams.size(); i++) {
1872 String paramType = methPrmTypes.get(i);
1873 String param = methParams.get(i);
1874 String simpleType = getSimpleType(paramType);
1875 if (isStructClass(simpleType)) {
1876 int methodNumId = intDecl.getMethodNumId(method);
1877 println("int struct" + methodNumId + "Size" + i + " = 0;");
1885 * HELPER: writeInputCountVarStructSkeleton() writes input counter variable of struct for skeleton
1887 private boolean writeInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
1889 List<String> methParams = intDecl.getMethodParams(method);
1890 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1891 boolean structExist = false;
1892 // Check for params with structs
1893 for (int i = 0; i < methParams.size(); i++) {
1894 String paramType = methPrmTypes.get(i);
1895 String param = methParams.get(i);
1896 String simpleType = getSimpleType(paramType);
1897 boolean begin = true;
1898 if (isStructClass(simpleType)) {
1901 print(", "); begin = false;
1903 int methodNumId = intDecl.getMethodNumId(method);
1904 print("struct" + methodNumId + "Size" + i);
1912 * HELPER: writeMethodCallStructSkeleton() writes method call for wait invoke in skeleton
1914 private void writeMethodCallStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1916 // Use this set to handle two same methodIds
1917 for (String method : methods) {
1919 List<String> methParams = intDecl.getMethodParams(method);
1920 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1921 // Check for params with structs
1922 for (int i = 0; i < methParams.size(); i++) {
1923 String paramType = methPrmTypes.get(i);
1924 String param = methParams.get(i);
1925 String simpleType = getSimpleType(paramType);
1926 if (isStructClass(simpleType)) {
1927 int methodNumId = intDecl.getMethodNumId(method);
1929 String helperMethod = methodNumId + "struct" + i;
1930 String tempVar = "struct" + methodNumId + "Size" + i;
1931 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
1932 print(tempVar + " = ___");
1933 println(helperMethod + "(); break;");
1941 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
1943 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1945 // Use this set to handle two same methodIds
1946 for (String method : methods) {
1948 List<String> methParams = intDecl.getMethodParams(method);
1949 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1950 // Check for params with structs
1951 for (int i = 0; i < methParams.size(); i++) {
1952 String paramType = methPrmTypes.get(i);
1953 String param = methParams.get(i);
1954 String simpleType = getSimpleType(paramType);
1955 if (isStructClass(simpleType)) {
1956 int methodNumId = intDecl.getMethodNumId(method);
1958 String helperMethod = methodNumId + "struct" + i;
1959 String tempVar = "struct" + methodNumId + "Size" + i;
1960 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
1961 print(tempVar + " = ___");
1962 println(helperMethod + "(rmiObj); break;");
1970 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
1972 private void writeJavaMethodPermission(String intface) {
1974 // Get all the different stubs
1975 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1976 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1977 String newIntface = intMeth.getKey();
1978 int newObjectId = mapNewIntfaceObjId.get(newIntface);
1979 println("if (_objectId == object" + newObjectId + "Id) {");
1980 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
1981 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
1984 println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");");
1992 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
1994 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
1996 // Use this set to handle two same methodIds
1997 Set<String> uniqueMethodIds = new HashSet<String>();
1998 println("private void ___waitRequestInvokeMethod() throws IOException {");
1999 // Write variables here if we have callbacks or enums or structs
2000 writeCountVarStructSkeleton(methods, intDecl);
2001 println("while (true) {");
2002 println("rmiObj.getMethodBytes();");
2003 println("int _objectId = rmiObj.getObjectId();");
2004 println("int methodId = rmiObj.getMethodId();");
2005 // Generate permission check
2006 writeJavaMethodPermission(intface);
2007 println("switch (methodId) {");
2008 // Print methods and method Ids
2009 for (String method : methods) {
2010 String methodId = intDecl.getMethodId(method);
2011 int methodNumId = intDecl.getMethodNumId(method);
2012 print("case " + methodNumId + ": ___");
2013 String helperMethod = methodId;
2014 if (uniqueMethodIds.contains(methodId))
2015 helperMethod = helperMethod + methodNumId;
2017 uniqueMethodIds.add(methodId);
2018 print(helperMethod + "(");
2019 writeInputCountVarStructSkeleton(method, intDecl);
2020 println("); break;");
2022 String method = "___initCallBack()";
2023 // Print case -9999 (callback handler) if callback exists
2024 if (callbackExist) {
2025 int methodId = intDecl.getHelperMethodNumId(method);
2026 println("case " + methodId + ": ___regCB(); break;");
2028 writeMethodCallStructSkeleton(methods, intDecl);
2029 println("default: ");
2030 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2038 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2040 public void generateJavaSkeletonClass() throws IOException {
2042 // Create a new directory
2043 String path = createDirectories(dir, subdir);
2044 for (String intface : mapIntfacePTH.keySet()) {
2045 // Open a new file to write into
2046 String newSkelClass = intface + "_Skeleton";
2047 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2048 pw = new PrintWriter(new BufferedWriter(fw));
2049 // Pass in set of methods and get import classes
2050 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2051 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2052 List<String> methods = intDecl.getMethods();
2053 Set<String> importClasses = getImportClasses(methods, intDecl);
2054 List<String> stdImportClasses = getStandardJavaImportClasses();
2055 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2056 printImportStatements(allImportClasses);
2057 // Find out if there are callback objects
2058 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2059 boolean callbackExist = !callbackClasses.isEmpty();
2060 // Write class header
2062 println("public class " + newSkelClass + " implements " + intface + " {\n");
2064 writePropertiesJavaSkeleton(intface, callbackExist, intDecl);
2065 // Write constructor
2066 writeConstructorJavaSkeleton(newSkelClass, intface);
2068 writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false);
2069 // Write method helper
2070 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2071 // Write waitRequestInvokeMethod() - main loop
2072 writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
2075 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2081 * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class
2083 private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) {
2085 println("private " + intface + " mainObj;");
2086 // For callback skeletons, this is its own object Id
2087 println("private static int objectId = 0;");
2089 if (callbackExist) {
2090 println("private static int objIdCnt = 0;");
2091 println("private IoTRMICall rmiCall;");
2098 * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class
2100 private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface) {
2102 println("public " + newSkelClass + "(" + intface + " _mainObj, int _objectId) throws Exception {");
2103 println("mainObj = _mainObj;");
2104 println("objectId = _objectId;");
2110 * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class
2112 private void writeMethodHelperJavaCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2114 // Use this set to handle two same methodIds
2115 Set<String> uniqueMethodIds = new HashSet<String>();
2116 for (String method : methods) {
2118 List<String> methParams = intDecl.getMethodParams(method);
2119 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2120 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
2121 String methodId = intDecl.getMethodId(method);
2122 print("public void ___");
2123 String helperMethod = methodId;
2124 if (uniqueMethodIds.contains(methodId))
2125 helperMethod = helperMethod + intDecl.getMethodNumId(method);
2127 uniqueMethodIds.add(methodId);
2128 String retType = intDecl.getMethodType(method);
2129 print(helperMethod + "(");
2130 boolean begin = true;
2131 for (int i = 0; i < methParams.size(); i++) { // Print size variables
2132 String paramType = methPrmTypes.get(i);
2133 String param = methParams.get(i);
2134 String simpleType = getSimpleType(paramType);
2135 if (isStructClass(simpleType)) {
2136 if (!begin) { // Generate comma for not the beginning variable
2137 print(", "); begin = false;
2139 int methodNumId = intDecl.getMethodNumId(method);
2140 print("int struct" + methodNumId + "Size" + i);
2143 // Check if this is "void"
2144 if (retType.equals("void"))
2145 println(", IoTRMIObject rmiObj) {");
2147 println(", IoTRMIObject rmiObj) throws IOException {");
2148 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
2151 String methodId = intDecl.getMethodId(method);
2152 print("public void ___");
2153 String helperMethod = methodId;
2154 if (uniqueMethodIds.contains(methodId))
2155 helperMethod = helperMethod + intDecl.getMethodNumId(method);
2157 uniqueMethodIds.add(methodId);
2158 // Check if this is "void"
2159 String retType = intDecl.getMethodType(method);
2160 if (retType.equals("void"))
2161 println(helperMethod + "(IoTRMIObject rmiObj) {");
2163 println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {");
2164 // Now, write the helper body of skeleton!
2165 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
2169 // Write method helper for structs
2170 writeMethodHelperStructSetupJavaCallbackSkeleton(methods, intDecl);
2175 * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the request invoke method of the callback skeleton class
2177 private void writeJavaCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
2179 // Use this set to handle two same methodIds
2180 Set<String> uniqueMethodIds = new HashSet<String>();
2181 println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {");
2182 // Write variables here if we have callbacks or enums or structs
2183 writeCountVarStructSkeleton(methods, intDecl);
2184 // Write variables here if we have callbacks or enums or structs
2185 println("int methodId = rmiObj.getMethodId();");
2186 // TODO: code the permission check here!
2187 println("switch (methodId) {");
2188 // Print methods and method Ids
2189 for (String method : methods) {
2190 String methodId = intDecl.getMethodId(method);
2191 int methodNumId = intDecl.getMethodNumId(method);
2192 print("case " + methodNumId + ": ___");
2193 String helperMethod = methodId;
2194 if (uniqueMethodIds.contains(methodId))
2195 helperMethod = helperMethod + methodNumId;
2197 uniqueMethodIds.add(methodId);
2198 print(helperMethod + "(");
2199 if (writeInputCountVarStructSkeleton(method, intDecl))
2200 println(", rmiObj); break;");
2202 println("rmiObj); break;");
2204 String method = "___initCallBack()";
2205 // Print case -9999 (callback handler) if callback exists
2206 if (callbackExist) {
2207 int methodId = intDecl.getHelperMethodNumId(method);
2208 println("case " + methodId + ": ___regCB(rmiObj); break;");
2210 writeMethodCallStructCallbackSkeleton(methods, intDecl);
2211 println("default: ");
2212 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2219 * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java
2221 public void generateJavaCallbackSkeletonClass() throws IOException {
2223 // Create a new directory
2224 String path = createDirectories(dir, subdir);
2225 for (String intface : mapIntfacePTH.keySet()) {
2226 // Open a new file to write into
2227 String newSkelClass = intface + "_CallbackSkeleton";
2228 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2229 pw = new PrintWriter(new BufferedWriter(fw));
2230 // Pass in set of methods and get import classes
2231 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2232 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2233 List<String> methods = intDecl.getMethods();
2234 Set<String> importClasses = getImportClasses(methods, intDecl);
2235 List<String> stdImportClasses = getStandardJavaImportClasses();
2236 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2237 printImportStatements(allImportClasses);
2238 // Find out if there are callback objects
2239 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2240 boolean callbackExist = !callbackClasses.isEmpty();
2241 // Write class header
2243 println("public class " + newSkelClass + " implements " + intface + " {\n");
2245 writePropertiesJavaCallbackSkeleton(intface, callbackExist);
2246 // Write constructor
2247 writeConstructorJavaCallbackSkeleton(newSkelClass, intface);
2249 writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true);
2250 // Write method helper
2251 writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses);
2252 // Write waitRequestInvokeMethod() - main loop
2253 writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
2256 System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java...");
2262 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2264 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2266 for (String method : methods) {
2268 List<String> methParams = intDecl.getMethodParams(method);
2269 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2270 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2271 intDecl.getMethodId(method) + "(");
2272 for (int i = 0; i < methParams.size(); i++) {
2273 // Check for params with driver class types and exchange it
2274 // with its remote interface
2275 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2276 paramType = checkAndGetCplusType(paramType);
2277 // Check for arrays - translate into vector in C++
2278 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2279 print(paramComplete);
2280 // Check if this is the last element (don't print a comma)
2281 if (i != methParams.size() - 1) {
2291 * HELPER: writeMethodCplusInterface() writes the method of the interface
2293 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2295 for (String method : methods) {
2297 List<String> methParams = intDecl.getMethodParams(method);
2298 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2299 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2300 intDecl.getMethodId(method) + "(");
2301 for (int i = 0; i < methParams.size(); i++) {
2302 // Check for params with driver class types and exchange it
2303 // with its remote interface
2304 String paramType = methPrmTypes.get(i);
2305 paramType = checkAndGetCplusType(paramType);
2306 // Check for arrays - translate into vector in C++
2307 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2308 print(paramComplete);
2309 // Check if this is the last element (don't print a comma)
2310 if (i != methParams.size() - 1) {
2320 * HELPER: generateEnumCplus() writes the enumeration declaration
2322 public void generateEnumCplus() throws IOException {
2324 // Create a new directory
2325 createDirectory(dir);
2326 for (String intface : mapIntfacePTH.keySet()) {
2327 // Get the right StructDecl
2328 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2329 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2330 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2331 // Iterate over enum declarations
2332 for (String enType : enumTypes) {
2333 // Open a new file to write into
2334 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2335 pw = new PrintWriter(new BufferedWriter(fw));
2336 // Write file headers
2337 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2338 println("#define _" + enType.toUpperCase() + "_HPP__");
2339 println("enum " + enType + " {");
2340 List<String> enumMembers = enumDecl.getMembers(enType);
2341 for (int i = 0; i < enumMembers.size(); i++) {
2343 String member = enumMembers.get(i);
2345 // Check if this is the last element (don't print a comma)
2346 if (i != enumMembers.size() - 1)
2354 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2361 * HELPER: generateStructCplus() writes the struct declaration
2363 public void generateStructCplus() throws IOException {
2365 // Create a new directory
2366 createDirectory(dir);
2367 for (String intface : mapIntfacePTH.keySet()) {
2368 // Get the right StructDecl
2369 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2370 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2371 List<String> structTypes = structDecl.getStructTypes();
2372 // Iterate over enum declarations
2373 for (String stType : structTypes) {
2374 // Open a new file to write into
2375 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2376 pw = new PrintWriter(new BufferedWriter(fw));
2377 // Write file headers
2378 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2379 println("#define _" + stType.toUpperCase() + "_HPP__");
2380 println("struct " + stType + " {");
2381 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2382 List<String> structMembers = structDecl.getMembers(stType);
2383 for (int i = 0; i < structMembers.size(); i++) {
2385 String memberType = structMemberTypes.get(i);
2386 String member = structMembers.get(i);
2387 String structTypeC = checkAndGetCplusType(memberType);
2388 String structComplete = checkAndGetCplusArray(structTypeC, member);
2389 println(structComplete + ";");
2394 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2401 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2403 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2404 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2405 * The local interface has to be the input parameter for the stub and the stub
2406 * interface has to be the input parameter for the local class.
2408 public void generateCplusLocalInterfaces() throws IOException {
2410 // Create a new directory
2411 createDirectory(dir);
2412 for (String intface : mapIntfacePTH.keySet()) {
2413 // Open a new file to write into
2414 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2415 pw = new PrintWriter(new BufferedWriter(fw));
2416 // Write file headers
2417 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2418 println("#define _" + intface.toUpperCase() + "_HPP__");
2419 println("#include <iostream>");
2420 // Pass in set of methods and get include classes
2421 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2422 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2423 List<String> methods = intDecl.getMethods();
2424 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2425 printIncludeStatements(includeClasses); println("");
2426 println("using namespace std;\n");
2427 //writeStructCplus(structDecl);
2428 println("class " + intface); println("{");
2431 writeMethodCplusLocalInterface(methods, intDecl);
2435 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2441 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2443 * For C++ we use virtual classe as interface
2445 public void generateCPlusInterfaces() throws IOException {
2447 // Create a new directory
2448 String path = createDirectories(dir, subdir);
2449 for (String intface : mapIntfacePTH.keySet()) {
2451 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2452 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2454 // Open a new file to write into
2455 String newIntface = intMeth.getKey();
2456 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2457 pw = new PrintWriter(new BufferedWriter(fw));
2458 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2459 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2460 // Write file headers
2461 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2462 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2463 println("#include <iostream>");
2464 // Pass in set of methods and get import classes
2465 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl, intface, false);
2466 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
2467 List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
2468 printIncludeStatements(allIncludeClasses); println("");
2469 println("using namespace std;\n");
2470 println("class " + newIntface);
2474 writeMethodCplusInterface(intMeth.getValue(), intDecl);
2478 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2485 * HELPER: writeMethodCplusStub() writes the methods of the stub
2487 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2489 for (String method : methods) {
2491 List<String> methParams = intDecl.getMethodParams(method);
2492 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2493 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2494 intDecl.getMethodId(method) + "(");
2495 boolean isCallbackMethod = false;
2496 String callbackType = null;
2497 for (int i = 0; i < methParams.size(); i++) {
2499 String paramType = methPrmTypes.get(i);
2500 // Check if this has callback object
2501 if (callbackClasses.contains(paramType)) {
2502 isCallbackMethod = true;
2503 callbackType = paramType;
2504 // Even if there're 2 callback arguments, we expect them to be of the same interface
2506 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2507 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2508 print(methParamComplete);
2509 // Check if this is the last element (don't print a comma)
2510 if (i != methParams.size() - 1) {
2515 if (isCallbackMethod)
2516 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2518 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method);
2520 // Write the init callback helper method
2521 if (isCallbackMethod) {
2522 writeInitCallbackCplusStub(callbackType, intDecl);
2523 writeInitCallbackSendInfoCplusStub(intDecl);
2530 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2532 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2533 List<String> methPrmTypes, String method, String callbackType) {
2535 // Check if this is single object, array, or list of objects
2536 boolean isArrayOrList = false;
2537 String callbackParam = null;
2538 for (int i = 0; i < methParams.size(); i++) {
2540 String paramType = methPrmTypes.get(i);
2541 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2542 String param = methParams.get(i);
2543 if (isArrayOrList(paramType, param)) { // Generate loop
2544 println("for (" + paramType + "* cb : " + getSimpleIdentifier(param) + ") {");
2545 println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
2546 isArrayOrList = true;
2547 callbackParam = getSimpleIdentifier(param);
2549 println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(" +
2550 getSimpleIdentifier(param) + ", objIdCnt++);");
2551 println("vecCallbackObj.push_back(skel);");
2552 if (isArrayOrList(paramType, param))
2556 println("int numParam = " + methParams.size() + ";");
2557 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2558 String retType = intDecl.getMethodType(method);
2559 String retTypeC = checkAndGetCplusType(retType);
2560 println("string retType = \"" + checkAndGetCplusArrayType(retTypeC) + "\";");
2561 // Generate array of parameter types
2562 print("string paramCls[] = { ");
2563 for (int i = 0; i < methParams.size(); i++) {
2564 String paramType = methPrmTypes.get(i);
2565 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2567 } else { // Generate normal classes if it's not a callback object
2568 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
2569 String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
2570 print("\"" + prmType + "\"");
2572 if (i != methParams.size() - 1) // Check if this is the last element
2576 print("int ___paramCB = ");
2578 println(callbackParam + ".size();");
2581 // Generate array of parameter objects
2582 print("void* paramObj[] = { ");
2583 for (int i = 0; i < methParams.size(); i++) {
2584 String paramType = methPrmTypes.get(i);
2585 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2586 print("&___paramCB");
2588 print(getSimpleIdentifier(methParams.get(i)));
2589 if (i != methParams.size() - 1)
2593 // Check if this is "void"
2594 if (retType.equals("void")) {
2595 println("void* retObj = NULL;");
2596 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2597 } else { // We do have a return value
2598 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2599 println(checkAndGetCplusType(retType) + " retVal;");
2601 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
2602 println("void* retObj = &retVal;");
2603 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2604 println("return retVal;");
2610 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2612 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2614 // Iterate and find enum declarations
2615 for (int i = 0; i < methParams.size(); i++) {
2616 String paramType = methPrmTypes.get(i);
2617 String param = methParams.get(i);
2618 String simpleType = getSimpleType(paramType);
2619 if (isEnumClass(simpleType)) {
2620 // Check if this is enum type
2621 if (isArrayOrList(paramType, param)) { // An array or vector
2622 println("int len" + i + " = " + param + ".size();");
2623 println("vector<int> paramEnum" + i + "(len);");
2624 println("for (int i = 0; i < len" + i + "; i++) {");
2625 println("paramEnum" + i + "[i] = (int) " + param + "[i];");
2627 } else { // Just one element
2628 println("vector<int> paramEnum" + i + "(1);");
2629 println("paramEnum" + i + "[0] = (int) " + param + ";");
2637 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2639 private void checkAndWriteEnumRetTypeCplusStub(String retType) {
2641 // Strips off array "[]" for return type
2642 String pureType = getSimpleArrayType(getSimpleType(retType));
2643 // Take the inner type of generic
2644 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2645 pureType = getTypeOfGeneric(retType)[0];
2646 if (isEnumClass(pureType)) {
2647 // Check if this is enum type
2648 println("vector<int> retEnumInt;");
2649 println("void* retObj = &retEnumInt;");
2650 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2651 if (isArrayOrList(retType, retType)) { // An array or vector
2652 println("int retLen = retEnumInt.size();");
2653 println("vector<" + pureType + "> retVal(retLen);");
2654 println("for (int i = 0; i < retLen; i++) {");
2655 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2657 } else { // Just one element
2658 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2660 println("return retVal;");
2666 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2668 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2669 InterfaceDecl intDecl, String method) {
2671 // Iterate and find struct declarations
2672 for (int i = 0; i < methParams.size(); i++) {
2673 String paramType = methPrmTypes.get(i);
2674 String param = methParams.get(i);
2675 String simpleType = getSimpleType(paramType);
2676 if (isStructClass(simpleType)) {
2677 // Check if this is enum type
2678 println("int numParam" + i + " = 1;");
2679 int methodNumId = intDecl.getMethodNumId(method);
2680 String helperMethod = methodNumId + "struct" + i;
2681 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2682 println("string retTypeStruct" + i + " = \"void\";");
2683 println("string paramClsStruct" + i + "[] = { \"int\" };");
2684 print("int structLen" + i + " = ");
2685 if (isArrayOrList(param, paramType)) { // An array
2686 println(getSimpleArrayType(param) + ".size();");
2687 } else { // Just one element
2690 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2691 println("void* retStructLen" + i + " = NULL;");
2692 println("rmiCall->remoteCall(objectId, methodIdStruct" + i +
2693 ", retTypeStruct" + i + ", paramClsStruct" + i + ", paramObjStruct" + i +
2694 ", numParam" + i + ", retStructLen" + i + ");\n");
2701 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2703 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2705 // Iterate and find struct declarations - count number of params
2706 for (int i = 0; i < methParams.size(); i++) {
2707 String paramType = methPrmTypes.get(i);
2708 String param = methParams.get(i);
2709 String simpleType = getGenericType(paramType);
2710 if (isStructClass(simpleType)) {
2711 int members = getNumOfMembers(simpleType);
2712 if (isArrayOrList(param, paramType)) { // An array
2713 String structLen = param + ".size()";
2714 print(members + "*" + structLen);
2716 print(Integer.toString(members));
2719 if (i != methParams.size() - 1) {
2727 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2729 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2731 // Get the struct declaration for this struct and generate initialization code
2732 StructDecl structDecl = getStructDecl(simpleType);
2733 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2734 List<String> members = structDecl.getMembers(simpleType);
2735 if (isArrayOrList(param, paramType)) { // An array or list
2736 println("for(int i = 0; i < " + param + ".size(); i++) {");
2738 if (isArrayOrList(param, paramType)) { // An array or list
2739 for (int i = 0; i < members.size(); i++) {
2740 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2741 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2742 println("paramCls[pos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
2743 print("paramObj[pos++] = &" + param + "[i].");
2744 print(getSimpleIdentifier(members.get(i)));
2748 } else { // Just one struct element
2749 for (int i = 0; i < members.size(); i++) {
2750 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2751 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2752 println("paramCls[pos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
2753 print("paramObj[pos++] = &" + param + ".");
2754 print(getSimpleIdentifier(members.get(i)));
2762 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2764 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2766 print("int numParam = ");
2767 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2769 println("void* paramObj[numParam];");
2770 println("string paramCls[numParam];");
2771 println("int pos = 0;");
2772 // Iterate again over the parameters
2773 for (int i = 0; i < methParams.size(); i++) {
2774 String paramType = methPrmTypes.get(i);
2775 String param = methParams.get(i);
2776 String simpleType = getGenericType(paramType);
2777 if (isStructClass(simpleType)) {
2778 writeStructMembersCplusStub(simpleType, paramType, param);
2780 String prmTypeC = checkAndGetCplusType(methPrmTypes.get(i));
2781 String prmType = checkAndGetCplusArrayType(prmTypeC, methParams.get(i));
2782 println("paramCls[pos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
2783 print("paramObj[pos++] = &");
2784 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2793 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2795 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2797 // Get the struct declaration for this struct and generate initialization code
2798 StructDecl structDecl = getStructDecl(simpleType);
2799 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2800 List<String> members = structDecl.getMembers(simpleType);
2801 if (isArrayOrList(retType, retType)) { // An array or list
2802 println("for(int i = 0; i < retLen; i++) {");
2804 if (isArrayOrList(retType, retType)) { // An array or list
2805 for (int i = 0; i < members.size(); i++) {
2806 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2807 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2808 println(" = retParam" + i + "[i];");
2811 } else { // Just one struct element
2812 for (int i = 0; i < members.size(); i++) {
2813 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2814 print("structRet." + getSimpleIdentifier(members.get(i)));
2815 println(" = retParam" + i + ";");
2818 println("return structRet;");
2823 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2825 private void writeStructReturnCplusStub(String simpleType, String retType) {
2827 // Minimum retLen is 1 if this is a single struct object
2828 println("int retLen = 0;");
2829 println("void* retLenObj = { &retLen };");
2830 // Handle the returned struct!!!
2831 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retLenObj);");
2832 int numMem = getNumOfMembers(simpleType);
2833 println("int numRet = " + numMem + "*retLen;");
2834 println("string retCls[numRet];");
2835 println("void* retObj[numRet];");
2836 StructDecl structDecl = getStructDecl(simpleType);
2837 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2838 List<String> members = structDecl.getMembers(simpleType);
2840 if (isArrayOrList(retType, retType)) { // An array or list
2841 for (int i = 0; i < members.size(); i++) {
2842 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2843 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2844 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2846 } else { // Just one struct element
2847 for (int i = 0; i < members.size(); i++) {
2848 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2849 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2850 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2853 println("int retPos = 0;");
2854 // Get the struct declaration for this struct and generate initialization code
2855 if (isArrayOrList(retType, retType)) { // An array or list
2856 println("for(int i = 0; i < retLen; i++) {");
2857 for (int i = 0; i < members.size(); i++) {
2858 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2859 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2860 println("retCls[retPos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
2861 println("retObj[retPos++] = &retParam" + i + "[i];");
2864 } else { // Just one struct element
2865 for (int i = 0; i < members.size(); i++) {
2866 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2867 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2868 println("retCls[retPos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
2869 println("retObj[retPos++] = &retParam" + i + ";");
2872 println("rmiCall->getStructObjects(retCls, numRet, retObj);");
2873 if (isArrayOrList(retType, retType)) { // An array or list
2874 println("vector<" + simpleType + "> structRet(retLen);");
2876 println(simpleType + " structRet;");
2877 writeStructRetMembersCplusStub(simpleType, retType);
2882 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
2884 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2885 List<String> methPrmTypes, String method) {
2887 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
2888 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2889 String retType = intDecl.getMethodType(method);
2890 String retTypeC = checkAndGetCplusType(retType);
2891 println("string retType = \"" + checkAndGetCplusArrayType(getStructType(getEnumType(retTypeC))) + "\";");
2892 // Generate array of parameter types
2893 if (isStructPresent(methParams, methPrmTypes)) {
2894 writeStructParamClassCplusStub(methParams, methPrmTypes);
2896 println("int numParam = " + methParams.size() + ";");
2897 print("string paramCls[] = { ");
2898 for (int i = 0; i < methParams.size(); i++) {
2899 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
2900 String paramType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
2901 print("\"" + getEnumType(paramType) + "\"");
2902 // Check if this is the last element (don't print a comma)
2903 if (i != methParams.size() - 1) {
2908 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
2909 // Generate array of parameter objects
2910 print("void* paramObj[] = { ");
2911 for (int i = 0; i < methParams.size(); i++) {
2912 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2913 // Check if this is the last element (don't print a comma)
2914 if (i != methParams.size() - 1) {
2920 // Check if this is "void"
2921 if (retType.equals("void")) {
2922 println("void* retObj = NULL;");
2923 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2924 } else { // We do have a return value
2925 // Generate array of parameter types
2926 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
2927 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType);
2929 // Check if the return value NONPRIMITIVES
2930 if (getParamCategory(retType) == ParamCategory.ENUM) {
2931 checkAndWriteEnumRetTypeCplusStub(retType);
2933 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2934 println(checkAndGetCplusType(retType) + " retVal;");
2936 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
2937 println("void* retObj = &retVal;");
2938 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2939 println("return retVal;");
2947 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
2949 private void writePropertiesCplusPermission(String intface) {
2951 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2952 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2953 String newIntface = intMeth.getKey();
2954 int newObjectId = mapNewIntfaceObjId.get(newIntface);
2955 println("const static int object" + newObjectId + "Id = " + newObjectId + ";");
2956 println("const static set<int> set" + newObjectId + "Allowed;");
2961 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
2963 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
2965 println("IoTRMICall *rmiCall;");
2966 //println("IoTRMIObject\t\t\t*rmiObj;");
2967 println("string address;");
2968 println("vector<int> ports;\n");
2969 // Get the object Id
2970 Integer objId = mapIntfaceObjId.get(intface);
2971 println("const static int objectId = " + objId + ";");
2972 mapNewIntfaceObjId.put(newIntface, objId);
2973 mapIntfaceObjId.put(intface, objId++);
2974 if (callbackExist) {
2975 // We assume that each class only has one callback interface for now
2976 Iterator it = callbackClasses.iterator();
2977 String callbackType = (String) it.next();
2978 println("// Callback properties");
2979 println("IoTRMIObject *rmiObj;");
2980 println("vector<" + callbackType + "*> vecCallbackObj;");
2981 println("static int objIdCnt;");
2982 // Generate permission stuff for callback stubs
2983 writePropertiesCplusPermission(callbackType);
2990 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
2992 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
2994 println(newStubClass +
2995 "(int _port, const char* _address, int _rev, bool* _bResult, vector<int> _ports) {");
2996 println("address = _address;");
2997 println("ports = _ports;");
2998 println("rmiCall = new IoTRMICall(_port, _address, _rev, _bResult);");
2999 if (callbackExist) {
3000 println("objIdCnt = 0;");
3001 Iterator it = callbackClasses.iterator();
3002 String callbackType = (String) it.next();
3003 println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
3004 println("th1.detach();");
3005 println("___regCB();");
3012 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3014 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3016 println("~" + newStubClass + "() {");
3017 println("if (rmiCall != NULL) {");
3018 println("delete rmiCall;");
3019 println("rmiCall = NULL;");
3021 if (callbackExist) {
3022 // We assume that each class only has one callback interface for now
3023 println("if (rmiObj != NULL) {");
3024 println("delete rmiObj;");
3025 println("rmiObj = NULL;");
3027 Iterator it = callbackClasses.iterator();
3028 String callbackType = (String) it.next();
3029 println("for(" + callbackType + "* cb : vecCallbackObj) {");
3030 println("delete cb;");
3031 println("cb = NULL;");
3040 * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
3042 private void writeCplusMethodCallbackPermission(String intface) {
3044 println("int methodId = IoTRMIObject::getMethodId(method);");
3045 // Get all the different stubs
3046 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3047 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3048 String newIntface = intMeth.getKey();
3049 int newObjectId = mapNewIntfaceObjId.get(newIntface);
3050 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
3051 println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
3052 println("exit(-1);");
3059 * HELPER: writeInitCallbackCplusStub() writes the initialization of callback
3061 private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl) {
3063 println("void ___initCallBack() {");
3064 println("bool bResult = false;");
3065 println("rmiObj = new IoTRMIObject(ports[0], &bResult);");
3066 println("while (true) {");
3067 println("char* method = rmiObj->getMethodBytes();");
3068 writeCplusMethodCallbackPermission(intface);
3069 println("int objId = IoTRMIObject::getObjectId(method);");
3070 println("if (objId < vecCallbackObj.size()) { // Check if still within range");
3071 println(intface + "_CallbackSkeleton* skel = dynamic_cast<" + intface +
3072 "_CallbackSkeleton*> (vecCallbackObj.at(objId));");
3073 println("skel->invokeMethod(rmiObj);");
3074 println("} else {");
3075 println("cerr << \"Illegal object Id: \" << to_string(objId);");
3076 // TODO: perhaps need to change this into "throw" to make it cleaner (allow stack unfolding)
3077 println("exit(-1);");
3085 * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization (send info part) of callback
3087 private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) {
3089 // Generate info sending part
3090 println("void ___regCB() {");
3091 println("int numParam = 3;");
3092 String method = "___initCallBack()";
3093 println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";");
3094 println("string retType = \"void\";");
3095 println("string paramCls[] = { \"int\", \"string\", \"int\" };");
3096 println("int rev = 0;");
3097 println("void* paramObj[] = { &ports[0], &address, &rev };");
3098 println("void* retObj = NULL;");
3099 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
3105 * generateCPlusStubClasses() generate stubs based on the methods list in C++
3107 public void generateCPlusStubClasses() throws IOException {
3109 // Create a new directory
3110 String path = createDirectories(dir, subdir);
3111 for (String intface : mapIntfacePTH.keySet()) {
3113 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3114 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3115 // Open a new file to write into
3116 String newIntface = intMeth.getKey();
3117 String newStubClass = newIntface + "_Stub";
3118 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3119 pw = new PrintWriter(new BufferedWriter(fw));
3120 // Write file headers
3121 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3122 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3123 println("#include <iostream>");
3124 // Find out if there are callback objects
3125 Set<String> methods = intMeth.getValue();
3126 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3127 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3128 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3129 boolean callbackExist = !callbackClasses.isEmpty();
3130 if (callbackExist) // Need thread library if this has callback
3131 println("#include <thread>");
3132 println("#include \"" + newIntface + ".hpp\""); println("");
3133 println("using namespace std;"); println("");
3134 println("class " + newStubClass + " : public " + newIntface); println("{");
3135 println("private:\n");
3136 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses);
3137 println("public:\n");
3138 // Add default constructor and destructor
3139 println(newStubClass + "() { }"); println("");
3140 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3141 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3143 writeMethodCplusStub(methods, intDecl, callbackClasses);
3144 print("}"); println(";");
3146 writePermissionInitializationCplus(intface, newStubClass, intDecl);
3149 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3156 * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class
3158 private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
3160 println("IoTRMICall *rmiCall;");
3161 // Get the object Id
3162 println("static int objectId;");
3163 if (callbackExist) {
3164 // We assume that each class only has one callback interface for now
3165 Iterator it = callbackClasses.iterator();
3166 String callbackType = (String) it.next();
3167 println("// Callback properties");
3168 println("IoTRMIObject *rmiObj;");
3169 println("vector<" + callbackType + "*> vecCallbackObj;");
3170 println("static int objIdCnt;");
3171 // TODO: Need to initialize address and ports if we want to have callback-in-callback
3172 println("string address;");
3173 println("vector<int> ports;\n");
3174 writePropertiesCplusPermission(callbackType);
3181 * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class
3183 private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3185 println(newStubClass + "(IoTRMICall* _rmiCall, int _objectId) {");
3186 println("objectId = _objectId;");
3187 println("rmiCall = _rmiCall;");
3188 if (callbackExist) {
3189 Iterator it = callbackClasses.iterator();
3190 String callbackType = (String) it.next();
3191 println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
3192 println("th1.detach();");
3193 println("___regCB();");
3200 * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++
3202 public void generateCPlusCallbackStubClasses() throws IOException {
3204 // Create a new directory
3205 String path = createDirectories(dir, subdir);
3206 for (String intface : mapIntfacePTH.keySet()) {
3208 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3209 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3210 // Open a new file to write into
3211 String newIntface = intMeth.getKey();
3212 String newStubClass = newIntface + "_CallbackStub";
3213 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3214 pw = new PrintWriter(new BufferedWriter(fw));
3215 // Find out if there are callback objects
3216 Set<String> methods = intMeth.getValue();
3217 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3218 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3219 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3220 boolean callbackExist = !callbackClasses.isEmpty();
3221 // Write file headers
3222 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3223 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3224 println("#include <iostream>");
3226 println("#include <thread>");
3227 println("#include \"" + newIntface + ".hpp\""); println("");
3228 println("using namespace std;"); println("");
3229 println("class " + newStubClass + " : public " + newIntface); println("{");
3230 println("private:\n");
3231 writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses);
3232 println("public:\n");
3233 // Add default constructor and destructor
3234 println(newStubClass + "() { }"); println("");
3235 writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses);
3236 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3238 writeMethodCplusStub(methods, intDecl, callbackClasses);
3241 writePermissionInitializationCplus(intface, newStubClass, intDecl);
3244 System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp...");
3251 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3253 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3255 println(intface + " *mainObj;");
3257 if (callbackExist) {
3258 Iterator it = callbackClasses.iterator();
3259 String callbackType = (String) it.next();
3260 String exchangeType = checkAndGetParamClass(callbackType);
3261 println("// Callback properties");
3262 println("static int objIdCnt;");
3263 println("vector<" + exchangeType + "*> vecCallbackObj;");
3264 println("IoTRMICall *rmiCall;");
3266 println("IoTRMIObject *rmiObj;\n");
3267 // Keep track of object Ids of all stubs registered to this interface
3268 writePropertiesCplusPermission(intface);
3274 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3276 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3278 // Keep track of object Ids of all stubs registered to this interface
3279 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3280 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3281 String newIntface = intMeth.getKey();
3282 int newObjectId = mapNewIntfaceObjId.get(newIntface);
3283 print("const set<int> " + newSkelClass + "::set" + newObjectId + "Allowed {");
3284 Set<String> methodIds = intMeth.getValue();
3286 for (String methodId : methodIds) {
3287 int methodNumId = intDecl.getMethodNumId(methodId);
3288 print(Integer.toString(methodNumId));
3289 // Check if this is the last element (don't print a comma)
3290 if (i != methodIds.size() - 1) {
3301 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3303 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist) {
3305 println(newSkelClass + "(" + intface + " *_mainObj, int _port) {");
3306 println("bool _bResult = false;");
3307 println("mainObj = _mainObj;");
3308 println("rmiObj = new IoTRMIObject(_port, &_bResult);");
3310 if (callbackExist) {
3311 println("objIdCnt = 0;");
3313 //println("set0Allowed = Arrays.asList(object0Permission);");
3314 println("___waitRequestInvokeMethod();");
3320 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3322 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3324 println("~" + newSkelClass + "() {");
3325 println("if (rmiObj != NULL) {");
3326 println("delete rmiObj;");
3327 println("rmiObj = NULL;");
3329 if (callbackExist) {
3330 // We assume that each class only has one callback interface for now
3331 println("if (rmiCall != NULL) {");
3332 println("delete rmiCall;");
3333 println("rmiCall = NULL;");
3335 Iterator it = callbackClasses.iterator();
3336 String callbackType = (String) it.next();
3337 String exchangeType = checkAndGetParamClass(callbackType);
3338 println("for(" + exchangeType + "* cb : vecCallbackObj) {");
3339 println("delete cb;");
3340 println("cb = NULL;");
3349 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3351 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3353 if (methodType.equals("void"))
3354 print("mainObj->" + methodId + "(");
3356 print("return mainObj->" + methodId + "(");
3357 for (int i = 0; i < methParams.size(); i++) {
3359 print(getSimpleIdentifier(methParams.get(i)));
3360 // Check if this is the last element (don't print a comma)
3361 if (i != methParams.size() - 1) {
3370 * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class
3372 private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton) {
3374 // This is a callback skeleton generation
3375 if (callbackSkeleton)
3376 println("void ___regCB(IoTRMIObject* rmiObj) {");
3378 println("void ___regCB() {");
3379 println("int numParam = 3;");
3380 println("int param1 = 0;");
3381 println("string param2 = \"\";");
3382 println("int param3 = 0;");
3383 println("void* paramObj[] = { ¶m1, ¶m2, ¶m3 };");
3384 println("bool bResult = false;");
3385 println("rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);");
3391 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3393 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3394 Set<String> callbackClasses, boolean callbackSkeleton) {
3396 for (String method : methods) {
3398 List<String> methParams = intDecl.getMethodParams(method);
3399 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3400 String methodId = intDecl.getMethodId(method);
3401 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3402 print(methodType + " " + methodId + "(");
3403 boolean isCallbackMethod = false;
3404 String callbackType = null;
3405 for (int i = 0; i < methParams.size(); i++) {
3407 String origParamType = methPrmTypes.get(i);
3408 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3409 isCallbackMethod = true;
3410 callbackType = origParamType;
3412 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3413 String methPrmType = checkAndGetCplusType(paramType);
3414 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3415 print(methParamComplete);
3416 // Check if this is the last element (don't print a comma)
3417 if (i != methParams.size() - 1) {
3422 // Now, write the body of skeleton!
3423 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3425 if (isCallbackMethod)
3426 writeInitCallbackCplusSkeleton(callbackSkeleton);
3432 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3434 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
3436 for (int i = 0; i < methParams.size(); i++) {
3437 String paramType = methPrmTypes.get(i);
3438 String param = methParams.get(i);
3439 //if (callbackType.equals(paramType)) {
3440 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3441 String exchParamType = checkAndGetParamClass(paramType);
3442 // Print array if this is array or list if this is a list of callback objects
3443 println("int numStubs" + i + " = 0;");
3450 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3452 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
3454 // Iterate over callback objects
3455 for (int i = 0; i < methParams.size(); i++) {
3456 String paramType = methPrmTypes.get(i);
3457 String param = methParams.get(i);
3458 // Generate a loop if needed
3459 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3460 String exchParamType = checkAndGetParamClass(paramType);
3461 if (isArrayOrList(paramType, param)) {
3462 println("vector<" + exchParamType + "> stub;");
3463 println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
3464 println(exchParamType + "* cb" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
3465 println("stub" + i + ".push_back(cb);");
3466 println("vecCallbackObj.push_back(cb);");
3467 println("objIdCnt++;");
3470 println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
3471 println("vecCallbackObj.push_back(stub" + i + ");");
3472 println("objIdCnt++;");
3480 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3482 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3484 // Iterate and find enum declarations
3485 for (int i = 0; i < methParams.size(); i++) {
3486 String paramType = methPrmTypes.get(i);
3487 String param = methParams.get(i);
3488 String simpleType = getSimpleType(paramType);
3489 if (isEnumClass(simpleType)) {
3490 // Check if this is enum type
3491 if (isArrayOrList(paramType, param)) { // An array
3492 println("int len" + i + " = paramEnumInt" + i + ".size();");
3493 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3494 println("for (int i=0; i < len" + i + "; i++) {");
3495 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3497 } else { // Just one element
3498 println(simpleType + " paramEnum" + i + ";");
3499 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3507 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3509 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3511 // Strips off array "[]" for return type
3512 String pureType = getSimpleArrayType(getSimpleType(retType));
3513 // Take the inner type of generic
3514 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3515 pureType = getTypeOfGeneric(retType)[0];
3516 if (isEnumClass(pureType)) {
3517 // Check if this is enum type
3519 if (isArrayOrList(retType, retType)) { // An array
3520 println("int retLen = retEnum.size();");
3521 println("vector<int> retEnumInt(retLen);");
3522 println("for (int i=0; i < retLen; i++) {");
3523 println("retEnumInt[i] = (int) retEnum[i];");
3525 } else { // Just one element
3526 println("vector<int> retEnumInt(1);");
3527 println("retEnumInt[0] = (int) retEnum;");
3534 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3536 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3537 Set<String> callbackClasses, String methodId) {
3539 print(methodId + "(");
3540 for (int i = 0; i < methParams.size(); i++) {
3541 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3542 if (callbackClasses.contains(paramType))
3544 else if (isEnumClass(getSimpleType(paramType))) // Check if this is enum type
3545 print("paramEnum" + i);
3546 else if (isStructClass(getSimpleType(paramType))) // Struct type
3547 print("paramStruct" + i);
3549 print(getSimpleIdentifier(methParams.get(i)));
3550 if (i != methParams.size() - 1) {
3559 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3561 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3562 List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
3563 String methodId, Set<String> callbackClasses) {
3565 println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
3566 if (isCallbackMethod)
3567 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3568 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3569 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3570 // Check if this is "void"
3571 String retType = intDecl.getMethodType(method);
3572 // Check if this is "void"
3573 if (retType.equals("void")) {
3574 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3575 } else { // We do have a return value
3576 if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) // Enum type
3577 print(checkAndGetCplusType(retType) + " retEnum = ");
3578 else if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) // Struct type
3579 print(checkAndGetCplusType(retType) + " retStruct = ");
3581 print(checkAndGetCplusType(retType) + " retVal = ");
3582 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3583 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3584 if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) // Struct type
3585 writeStructReturnCplusSkeleton(getSimpleArrayType(getSimpleType(retType)), retType);
3586 if (isEnumClass(getSimpleArrayType(getSimpleType(retType)))) // Enum type
3587 println("void* retObj = &retEnumInt;");
3589 if (!isStructClass(getSimpleArrayType(getSimpleType(retType)))) // Struct type
3590 println("void* retObj = &retVal;");
3591 String retTypeC = checkAndGetCplusType(retType);
3592 if (isStructClass(getSimpleArrayType(getSimpleType(retType)))) // Struct type
3593 println("rmiObj->sendReturnObj(retObj, retCls, numRetObj);");
3595 println("rmiObj->sendReturnObj(retObj, \"" + getEnumType(checkAndGetCplusArrayType(retTypeC)) + "\");");
3601 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3603 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3604 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3606 // Generate array of parameter types
3607 boolean isCallbackMethod = false;
3608 String callbackType = null;
3609 print("string paramCls[] = { ");
3610 for (int i = 0; i < methParams.size(); i++) {
3611 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3612 if (callbackClasses.contains(paramType)) {
3613 isCallbackMethod = true;
3614 callbackType = paramType;
3616 } else { // Generate normal classes if it's not a callback object
3617 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3618 String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
3619 print("\"" + getEnumType(prmType) + "\"");
3621 if (i != methParams.size() - 1) {
3626 println("int numParam = " + methParams.size() + ";");
3627 if (isCallbackMethod)
3628 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3629 // Generate parameters
3630 for (int i = 0; i < methParams.size(); i++) {
3631 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3632 if (!callbackClasses.contains(paramType)) {
3633 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
3634 if (isEnumClass(getSimpleType(methPrmType))) { // Check if this is enum type
3635 println("vector<int> paramEnumInt" + i + ";");
3637 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3638 println(methParamComplete + ";");
3642 // Generate array of parameter objects
3643 print("void* paramObj[] = { ");
3644 for (int i = 0; i < methParams.size(); i++) {
3645 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3646 if (callbackClasses.contains(paramType))
3647 print("&numStubs" + i);
3648 else if (isEnumClass(getSimpleType(paramType))) // Check if this is enum type
3649 print("¶mEnumInt" + i);
3651 print("&" + getSimpleIdentifier(methParams.get(i)));
3652 if (i != methParams.size() - 1) {
3657 // Write the return value part
3658 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3659 callbackType, methodId, callbackClasses);
3664 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3666 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3667 String param, String method, InterfaceDecl intDecl, int iVar) {
3669 // Get the struct declaration for this struct and generate initialization code
3670 StructDecl structDecl = getStructDecl(simpleType);
3671 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3672 List<String> members = structDecl.getMembers(simpleType);
3673 int methodNumId = intDecl.getMethodNumId(method);
3674 String counter = "struct" + methodNumId + "Size" + iVar;
3675 if (isArrayOrList(param, paramType)) { // An array or list
3676 println("for(int i = 0; i < " + counter + "; i++) {");
3679 if (isArrayOrList(param, paramType)) { // An array or list
3680 for (int i = 0; i < members.size(); i++) {
3681 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3682 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3683 println(getSimpleType(getEnumType(prmType)) + " param" + i + "[" + counter + "];");
3685 } else { // Just one struct element
3686 for (int i = 0; i < members.size(); i++) {
3687 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3688 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3689 println(getSimpleType(getEnumType(prmType)) + " param" + i + ";");
3692 println("int pos = 0;");
3693 if (isArrayOrList(param, paramType)) { // An array or list
3694 println("for(int i = 0; i < retLen; i++) {");
3695 for (int i = 0; i < members.size(); i++) {
3696 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3697 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3698 println("paramCls[pos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
3699 println("paramObj[pos++] = ¶m" + i + "[i];");
3702 } else { // Just one struct element
3703 for (int i = 0; i < members.size(); i++) {
3704 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3705 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3706 println("paramCls[pos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
3707 println("paramObj[pos++] = ¶m" + i + ";");
3714 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3716 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3717 List<String> methPrmTypes, String method) {
3719 for (int i = 0; i < methParams.size(); i++) {
3720 String paramType = methPrmTypes.get(i);
3721 String param = methParams.get(i);
3722 String simpleType = getGenericType(paramType);
3723 if (isStructClass(simpleType)) {
3724 int methodNumId = intDecl.getMethodNumId(method);
3725 String counter = "struct" + methodNumId + "Size" + i;
3727 if (isArrayOrList(param, paramType)) { // An array or list
3728 println("vector<" + simpleType + "> paramStruct" + i + ";");
3730 println(simpleType + " paramStruct" + i + ";");
3731 // Initialize members
3732 StructDecl structDecl = getStructDecl(simpleType);
3733 List<String> members = structDecl.getMembers(simpleType);
3734 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3735 if (isArrayOrList(param, paramType)) { // An array or list
3736 println("for(int i = 0; i < " + counter + "; i++) {");
3737 for (int j = 0; j < members.size(); j++) {
3738 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3739 println(" = param" + j + "[i];");
3742 } else { // Just one struct element
3743 for (int j = 0; j < members.size(); j++) {
3744 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3745 println(" = param" + j + ";");
3754 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3756 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3758 // Minimum retLen is 1 if this is a single struct object
3759 if (isArrayOrList(retType, retType))
3760 println("int retLen = retStruct.size();");
3761 else // Just single struct object
3762 println("int retLen = 1;");
3763 println("void* retLenObj = &retLen;");
3764 println("rmiObj->sendReturnObj(retLenObj, \"int\");");
3765 int numMem = getNumOfMembers(simpleType);
3766 println("int numRetObj = " + numMem + "*retLen;");
3767 println("string retCls[numRetObj];");
3768 println("void* retObj[numRetObj];");
3769 println("int retPos = 0;");
3770 // Get the struct declaration for this struct and generate initialization code
3771 StructDecl structDecl = getStructDecl(simpleType);
3772 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3773 List<String> members = structDecl.getMembers(simpleType);
3774 if (isArrayOrList(retType, retType)) { // An array or list
3775 println("for(int i = 0; i < retLen; i++) {");
3776 for (int i = 0; i < members.size(); i++) {
3777 String paramTypeC = checkAndGetCplusType(memTypes.get(i));
3778 String prmType = checkAndGetCplusArrayType(paramTypeC, members.get(i));
3779 println("retCls[retPos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
3780 print("retObj[retPos++] = &retStruct[i].");
3781 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3785 } else { // Just one struct element
3786 for (int i = 0; i < members.size(); i++) {
3787 String paramTypeC = checkAndGetCplusType(memTypes.get(i));
3788 String prmType = checkAndGetCplusArrayType(paramTypeC, members.get(i));
3789 println("retCls[retPos] = \"" + getSimpleType(getEnumType(prmType)) + "\";");
3790 print("retObj[retPos++] = &retStruct.");
3791 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3800 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3802 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3803 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3805 // Generate array of parameter objects
3806 boolean isCallbackMethod = false;
3807 String callbackType = null;
3808 print("int numParam = ");
3809 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3811 println("string paramCls[numParam];");
3812 println("void* paramObj[numParam];");
3813 // Iterate again over the parameters
3814 for (int i = 0; i < methParams.size(); i++) {
3815 String paramType = methPrmTypes.get(i);
3816 String param = methParams.get(i);
3817 String simpleType = getGenericType(paramType);
3818 if (isStructClass(simpleType)) {
3819 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3821 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3822 if (callbackClasses.contains(prmType)) {
3823 isCallbackMethod = true;
3824 callbackType = paramType;
3825 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3826 println("paramCls[pos] = \"int\";");
3827 println("paramObj[pos++] = &numStubs" + i + ";");
3828 } else { // Generate normal classes if it's not a callback object
3829 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3830 String prmTypeC = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
3831 if (isEnumClass(getSimpleType(paramTypeC))) { // Check if this is enum type
3832 println("vector<int> paramEnumInt" + i + ";");
3834 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3835 println(methParamComplete + ";");
3837 println("paramCls[pos] = \"" + getEnumType(prmTypeC) + "\";");
3838 if (isEnumClass(getSimpleType(paramType))) // Check if this is enum type
3839 println("paramObj[pos++] = ¶mEnumInt" + i);
3841 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3845 // Write the return value part
3846 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3847 callbackType, methodId, callbackClasses);
3852 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
3854 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
3856 // Use this set to handle two same methodIds
3857 Set<String> uniqueMethodIds = new HashSet<String>();
3858 for (String method : methods) {
3860 List<String> methParams = intDecl.getMethodParams(method);
3861 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3862 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
3863 String methodId = intDecl.getMethodId(method);
3865 String helperMethod = methodId;
3866 if (uniqueMethodIds.contains(methodId))
3867 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3869 uniqueMethodIds.add(methodId);
3870 String retType = intDecl.getMethodType(method);
3871 print(helperMethod + "(");
3872 boolean begin = true;
3873 for (int i = 0; i < methParams.size(); i++) { // Print size variables
3874 String paramType = methPrmTypes.get(i);
3875 String param = methParams.get(i);
3876 String simpleType = getSimpleType(paramType);
3877 if (isStructClass(simpleType)) {
3878 if (!begin) { // Generate comma for not the beginning variable
3879 print(", "); begin = false;
3881 int methodNumId = intDecl.getMethodNumId(method);
3882 print("int struct" + methodNumId + "Size" + i);
3886 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
3889 String methodId = intDecl.getMethodId(method);
3891 String helperMethod = methodId;
3892 if (uniqueMethodIds.contains(methodId))
3893 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3895 uniqueMethodIds.add(methodId);
3896 // Check if this is "void"
3897 String retType = intDecl.getMethodType(method);
3898 println(helperMethod + "() {");
3899 // Now, write the helper body of skeleton!
3900 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
3904 // Write method helper for structs
3905 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl);
3910 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
3912 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
3913 InterfaceDecl intDecl) {
3915 // Use this set to handle two same methodIds
3916 for (String method : methods) {
3918 List<String> methParams = intDecl.getMethodParams(method);
3919 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3920 // Check for params with structs
3921 for (int i = 0; i < methParams.size(); i++) {
3922 String paramType = methPrmTypes.get(i);
3923 String param = methParams.get(i);
3924 String simpleType = getSimpleType(paramType);
3925 if (isStructClass(simpleType)) {
3926 int methodNumId = intDecl.getMethodNumId(method);
3928 String helperMethod = methodNumId + "struct" + i;
3929 println(helperMethod + "() {");
3930 // Now, write the helper body of skeleton!
3931 println("string paramCls[] = { \"int\" };");
3932 println("int numParam = 1;");
3933 println("int param0 = 0;");
3934 println("void* paramObj[] = { ¶m0 };");
3935 println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
3936 println("return param0;");
3945 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
3947 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
3948 InterfaceDecl intDecl) {
3950 // Use this set to handle two same methodIds
3951 for (String method : methods) {
3953 List<String> methParams = intDecl.getMethodParams(method);
3954 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3955 // Check for params with structs
3956 for (int i = 0; i < methParams.size(); i++) {
3957 String paramType = methPrmTypes.get(i);
3958 String param = methParams.get(i);
3959 String simpleType = getSimpleType(paramType);
3960 if (isStructClass(simpleType)) {
3961 int methodNumId = intDecl.getMethodNumId(method);
3963 String helperMethod = methodNumId + "struct" + i;
3964 println(helperMethod + "(IoTRMIObject* rmiObj) {");
3965 // Now, write the helper body of skeleton!
3966 println("string paramCls[] = { \"int\" };");
3967 println("int numParam = 1;");
3968 println("int param0 = 0;");
3969 println("void* paramObj[] = { ¶m0 };");
3970 println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
3971 println("return param0;");
3980 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
3982 private void writeCplusMethodPermission(String intface) {
3984 // Get all the different stubs
3985 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3986 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3987 String newIntface = intMeth.getKey();
3988 int newObjectId = mapNewIntfaceObjId.get(newIntface);
3989 println("if (_objectId == object" + newObjectId + "Id) {");
3990 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
3991 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
3992 println("exit(-1);");
3995 println("cerr << \"Object Id: \" << _objectId << \" not recognized!\" << endl;");
3996 println("exit(-1);");
4004 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4006 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
4008 // Use this set to handle two same methodIds
4009 Set<String> uniqueMethodIds = new HashSet<String>();
4010 println("void ___waitRequestInvokeMethod() {");
4011 // Write variables here if we have callbacks or enums or structs
4012 writeCountVarStructSkeleton(methods, intDecl);
4013 println("while (true) {");
4014 println("rmiObj->getMethodBytes();");
4015 println("int _objectId = rmiObj->getObjectId();");
4016 println("int methodId = rmiObj->getMethodId();");
4017 // Generate permission check
4018 writeCplusMethodPermission(intface);
4019 println("switch (methodId) {");
4020 // Print methods and method Ids
4021 for (String method : methods) {
4022 String methodId = intDecl.getMethodId(method);
4023 int methodNumId = intDecl.getMethodNumId(method);
4024 print("case " + methodNumId + ": ___");
4025 String helperMethod = methodId;
4026 if (uniqueMethodIds.contains(methodId))
4027 helperMethod = helperMethod + methodNumId;
4029 uniqueMethodIds.add(methodId);
4030 print(helperMethod + "(");
4031 writeInputCountVarStructSkeleton(method, intDecl);
4032 println("); break;");
4034 String method = "___initCallBack()";
4035 // Print case -9999 (callback handler) if callback exists
4036 if (callbackExist) {
4037 int methodId = intDecl.getHelperMethodNumId(method);
4038 println("case " + methodId + ": ___regCB(); break;");
4040 writeMethodCallStructSkeleton(methods, intDecl);
4041 println("default: ");
4042 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4043 println("throw exception();");
4051 * generateCplusSkeletonClass() generate skeletons based on the methods list in C++
4053 public void generateCplusSkeletonClass() throws IOException {
4055 // Create a new directory
4056 String path = createDirectories(dir, subdir);
4057 for (String intface : mapIntfacePTH.keySet()) {
4058 // Open a new file to write into
4059 String newSkelClass = intface + "_Skeleton";
4060 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4061 pw = new PrintWriter(new BufferedWriter(fw));
4062 // Write file headers
4063 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4064 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4065 println("#include <iostream>");
4066 println("#include \"" + intface + ".hpp\"\n");
4067 // Pass in set of methods and get import classes
4068 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4069 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4070 List<String> methods = intDecl.getMethods();
4071 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
4072 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4073 List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
4074 printIncludeStatements(allIncludeClasses); println("");
4075 println("using namespace std;\n");
4076 // Find out if there are callback objects
4077 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4078 boolean callbackExist = !callbackClasses.isEmpty();
4079 // Write class header
4080 println("class " + newSkelClass + " : public " + intface); println("{");
4081 println("private:\n");
4083 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4084 println("public:\n");
4085 // Write constructor
4086 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist);
4087 // Write deconstructor
4088 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4090 writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false);
4091 // Write method helper
4092 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses);
4093 // Write waitRequestInvokeMethod() - main loop
4094 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
4096 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4099 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4105 * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class
4107 private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
4109 println(intface + " *mainObj;");
4110 // Keep track of object Ids of all stubs registered to this interface
4111 println("static int objectId;");
4113 if (callbackExist) {
4114 Iterator it = callbackClasses.iterator();
4115 String callbackType = (String) it.next();
4116 String exchangeType = checkAndGetParamClass(callbackType);
4117 println("// Callback properties");
4118 println("IoTRMICall* rmiCall;");
4119 println("vector<" + exchangeType + "*> vecCallbackObj;");
4120 println("static int objIdCnt;");
4127 * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class
4129 private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist) {
4131 println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {");
4132 println("mainObj = _mainObj;");
4133 println("objectId = _objectId;");
4135 if (callbackExist) {
4136 println("objIdCnt = 0;");
4143 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
4145 private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist,
4146 Set<String> callbackClasses) {
4148 println("~" + newStubClass + "() {");
4149 if (callbackExist) {
4150 // We assume that each class only has one callback interface for now
4151 println("if (rmiCall != NULL) {");
4152 println("delete rmiCall;");
4153 println("rmiCall = NULL;");
4155 Iterator it = callbackClasses.iterator();
4156 String callbackType = (String) it.next();
4157 String exchangeType = checkAndGetParamClass(callbackType);
4158 println("for(" + exchangeType + "* cb : vecCallbackObj) {");
4159 println("delete cb;");
4160 println("cb = NULL;");
4169 * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of callback skeleton class
4171 private void writeMethodHelperCplusCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4172 Set<String> callbackClasses) {
4174 // Use this set to handle two same methodIds
4175 Set<String> uniqueMethodIds = new HashSet<String>();
4176 for (String method : methods) {
4178 List<String> methParams = intDecl.getMethodParams(method);
4179 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4180 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4181 String methodId = intDecl.getMethodId(method);
4183 String helperMethod = methodId;
4184 if (uniqueMethodIds.contains(methodId))
4185 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4187 uniqueMethodIds.add(methodId);
4188 String retType = intDecl.getMethodType(method);
4189 print(helperMethod + "(");
4190 boolean begin = true;
4191 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4192 String paramType = methPrmTypes.get(i);
4193 String param = methParams.get(i);
4194 String simpleType = getSimpleType(paramType);
4195 if (isStructClass(simpleType)) {
4196 if (!begin) { // Generate comma for not the beginning variable
4197 print(", "); begin = false;
4199 int methodNumId = intDecl.getMethodNumId(method);
4200 print("int struct" + methodNumId + "Size" + i);
4203 println(", IoTRMIObject* rmiObj) {");
4204 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4207 String methodId = intDecl.getMethodId(method);
4209 String helperMethod = methodId;
4210 if (uniqueMethodIds.contains(methodId))
4211 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4213 uniqueMethodIds.add(methodId);
4214 // Check if this is "void"
4215 String retType = intDecl.getMethodType(method);
4216 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4217 // Now, write the helper body of skeleton!
4218 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4222 // Write method helper for structs
4223 writeMethodHelperStructSetupCplusCallbackSkeleton(methods, intDecl);
4228 * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the request invoke method of the skeleton callback class
4230 private void writeCplusCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4231 boolean callbackExist) {
4233 // Use this set to handle two same methodIds
4234 Set<String> uniqueMethodIds = new HashSet<String>();
4235 println("void invokeMethod(IoTRMIObject* rmiObj) {");
4236 // Write variables here if we have callbacks or enums or structs
4237 writeCountVarStructSkeleton(methods, intDecl);
4238 // Write variables here if we have callbacks or enums or structs
4239 println("int methodId = rmiObj->getMethodId();");
4240 // TODO: code the permission check here!
4241 println("switch (methodId) {");
4242 // Print methods and method Ids
4243 for (String method : methods) {
4244 String methodId = intDecl.getMethodId(method);
4245 int methodNumId = intDecl.getMethodNumId(method);
4246 print("case " + methodNumId + ": ___");
4247 String helperMethod = methodId;
4248 if (uniqueMethodIds.contains(methodId))
4249 helperMethod = helperMethod + methodNumId;
4251 uniqueMethodIds.add(methodId);
4252 print(helperMethod + "(");
4253 if (writeInputCountVarStructSkeleton(method, intDecl))
4254 println(", rmiObj); break;");
4256 println("rmiObj); break;");
4258 String method = "___initCallBack()";
4259 // Print case -9999 (callback handler) if callback exists
4260 if (callbackExist) {
4261 int methodId = intDecl.getHelperMethodNumId(method);
4262 println("case " + methodId + ": ___regCB(rmiObj); break;");
4264 writeMethodCallStructCallbackSkeleton(methods, intDecl);
4265 println("default: ");
4266 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4267 println("throw exception();");
4274 * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++
4276 public void generateCplusCallbackSkeletonClass() throws IOException {
4278 // Create a new directory
4279 String path = createDirectories(dir, subdir);
4280 for (String intface : mapIntfacePTH.keySet()) {
4281 // Open a new file to write into
4282 String newSkelClass = intface + "_CallbackSkeleton";
4283 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4284 pw = new PrintWriter(new BufferedWriter(fw));
4285 // Write file headers
4286 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4287 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4288 println("#include <iostream>");
4289 println("#include \"" + intface + ".hpp\"\n");
4290 // Pass in set of methods and get import classes
4291 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4292 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4293 List<String> methods = intDecl.getMethods();
4294 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
4295 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4296 List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
4297 printIncludeStatements(allIncludeClasses); println("");
4298 // Find out if there are callback objects
4299 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4300 boolean callbackExist = !callbackClasses.isEmpty();
4301 println("using namespace std;\n");
4302 // Write class header
4303 println("class " + newSkelClass + " : public " + intface); println("{");
4304 println("private:\n");
4306 writePropertiesCplusCallbackSkeleton(intface, callbackExist, callbackClasses);
4307 println("public:\n");
4308 // Write constructor
4309 writeConstructorCplusCallbackSkeleton(newSkelClass, intface, callbackExist);
4310 // Write deconstructor
4311 writeDeconstructorCplusCallbackSkeleton(newSkelClass, callbackExist, callbackClasses);
4313 writeMethodCplusSkeleton(methods, intDecl, callbackClasses, true);
4314 // Write method helper
4315 writeMethodHelperCplusCallbackSkeleton(methods, intDecl, callbackClasses);
4316 // Write waitRequestInvokeMethod() - main loop
4317 writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
4321 System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp...");
4327 * generateInitializer() generate initializer based on type
4329 public String generateCplusInitializer(String type) {
4331 // Generate dummy returns for now
4332 if (type.equals("short")||
4333 type.equals("int") ||
4334 type.equals("long") ||
4335 type.equals("float")||
4336 type.equals("double")) {
4339 } else if ( type.equals("String") ||
4340 type.equals("string")) {
4343 } else if ( type.equals("char") ||
4344 type.equals("byte")) {
4347 } else if ( type.equals("boolean")) {
4357 * setDirectory() sets a new directory for stub files
4359 public void setDirectory(String _subdir) {
4366 * printUsage() prints the usage of this compiler
4368 public static void printUsage() {
4370 System.out.println();
4371 System.out.println("Sentinel interface and stub compiler version 1.0");
4372 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4373 System.out.println("All rights reserved.");
4374 System.out.println("Usage:");
4375 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4376 System.out.println("\t\tDisplay this help texts\n\n");
4377 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4378 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4379 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4380 System.out.println("Options:");
4381 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
4382 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
4383 System.out.println();
4388 * parseFile() prepares Lexer and Parser objects, then parses the file
4390 public static ParseNode parseFile(String file) {
4392 ParseNode pn = null;
4394 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4395 ScannerBuffer lexer =
4396 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4397 Parser parse = new Parser(lexer,csf);
4398 pn = (ParseNode) parse.parse().value;
4399 } catch (Exception e) {
4400 e.printStackTrace();
4401 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
4409 * Basic helper functions
4412 boolean newline=true;
4415 private void print(String str) {
4418 if (str.equals("}"))
4420 for(int i=0; i<tab; i++)
4430 * This function converts Java to C++ type for compilation
4432 private String convertType(String jType) {
4434 return mapPrimitives.get(jType);
4439 * A collection of methods with print-to-file functionality
4441 private void println(String str) {
4444 if (str.contains("}") && !str.contains("{"))
4446 for(int i=0; i<tab; i++)
4455 private void updatetabbing(String str) {
4457 tablevel+=count(str,'{')-count(str,'}');
4461 private int count(String str, char key) {
4462 char[] array = str.toCharArray();
4464 for(int i=0; i<array.length; i++) {
4465 if (array[i] == key)
4472 private void createDirectory(String dirName) {
4474 File file = new File(dirName);
4475 if (!file.exists()) {
4477 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4479 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4482 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4487 // Create a directory and possibly a sub directory
4488 private String createDirectories(String dir, String subdir) {
4491 createDirectory(path);
4492 if (subdir != null) {
4493 path = path + "/" + subdir;
4494 createDirectory(path);
4500 // Inserting array members into a Map object
4501 // that maps arrKey to arrVal objects
4502 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4504 for(int i = 0; i < arrKey.length; i++) {
4506 map.put(arrKey[i], arrVal[i]);
4511 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4512 private ParamCategory getParamCategory(String paramType) {
4514 if (mapPrimitives.containsKey(paramType)) {
4515 return ParamCategory.PRIMITIVES;
4516 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4517 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4518 return ParamCategory.NONPRIMITIVES;
4519 } else if (isEnumClass(paramType)) {
4520 return ParamCategory.ENUM;
4521 } else if (isStructClass(paramType)) {
4522 return ParamCategory.STRUCT;
4524 return ParamCategory.USERDEFINED;
4528 // Return full class name for non-primitives to generate Java import statements
4529 // e.g. java.util.Set for Set
4530 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4532 return mapNonPrimitivesJava.get(paramNonPrimitives);
4536 // Return full class name for non-primitives to generate Cplus include statements
4537 // e.g. #include <set> for Set
4538 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4540 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4544 // Get simple types, e.g. HashSet for HashSet<...>
4545 // Basically strip off the "<...>"
4546 private String getSimpleType(String paramType) {
4548 // Check if this is generics
4549 if(paramType.contains("<")) {
4550 String[] type = paramType.split("<");
4557 // Generate a set of standard classes for import statements
4558 private List<String> getStandardJavaImportClasses() {
4560 List<String> importClasses = new ArrayList<String>();
4561 // Add the standard list first
4562 importClasses.add("java.io.IOException");
4563 importClasses.add("java.util.List");
4564 importClasses.add("java.util.ArrayList");
4565 importClasses.add("java.util.Arrays");
4566 importClasses.add("iotrmi.Java.IoTRMICall");
4567 importClasses.add("iotrmi.Java.IoTRMIObject");
4569 return importClasses;
4573 // Generate a set of standard classes for import statements
4574 private List<String> getStandardCplusIncludeClasses() {
4576 List<String> importClasses = new ArrayList<String>();
4577 // Add the standard list first
4578 importClasses.add("<vector>");
4579 importClasses.add("<set>");
4580 importClasses.add("\"IoTRMICall.hpp\"");
4581 importClasses.add("\"IoTRMIObject.hpp\"");
4583 return importClasses;
4587 // Combine all classes for import statements
4588 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4590 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4591 // Iterate over the list of import classes
4592 for (String str : libClasses) {
4593 if (!allLibClasses.contains(str)) {
4594 allLibClasses.add(str);
4597 return allLibClasses;
4602 // Generate a set of classes for import statements
4603 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4605 Set<String> importClasses = new HashSet<String>();
4606 for (String method : methods) {
4607 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4608 for (String paramType : methPrmTypes) {
4610 String simpleType = getSimpleType(paramType);
4611 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4612 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4616 return importClasses;
4620 // Handle and return the correct enum declaration
4621 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4622 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4624 // Strips off array "[]" for return type
4625 String pureType = getSimpleArrayType(type);
4626 // Take the inner type of generic
4627 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4628 pureType = getTypeOfGeneric(type)[0];
4629 if (isEnumClass(pureType)) {
4630 String enumType = intDecl.getInterface() + "." + type;
4637 // Handle and return the correct type
4638 private String getEnumParam(String type, String param, int i) {
4640 // Strips off array "[]" for return type
4641 String pureType = getSimpleArrayType(type);
4642 // Take the inner type of generic
4643 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4644 pureType = getTypeOfGeneric(type)[0];
4645 if (isEnumClass(pureType)) {
4646 String enumParam = "paramEnum" + i;
4653 // Handle and return the correct enum declaration translate into int[]
4654 private String getEnumType(String type) {
4656 // Strips off array "[]" for return type
4657 String pureType = getSimpleArrayType(type);
4658 // Take the inner type of generic
4659 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4660 pureType = getTypeOfGeneric(type)[0];
4661 if (isEnumClass(pureType)) {
4662 String enumType = "int[]";
4669 // Handle and return the correct struct declaration
4670 private String getStructType(String type) {
4672 // Strips off array "[]" for return type
4673 String pureType = getSimpleArrayType(type);
4674 // Take the inner type of generic
4675 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4676 pureType = getTypeOfGeneric(type)[0];
4677 if (isStructClass(pureType)) {
4678 String structType = "int";
4685 // Check if this an enum declaration
4686 private boolean isEnumClass(String type) {
4688 // Just iterate over the set of interfaces
4689 for (String intface : mapIntfacePTH.keySet()) {
4690 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4691 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4692 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4693 if (setEnumDecl.contains(type))
4700 // Check if this an struct declaration
4701 private boolean isStructClass(String type) {
4703 // Just iterate over the set of interfaces
4704 for (String intface : mapIntfacePTH.keySet()) {
4705 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4706 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4707 List<String> listStructDecl = structDecl.getStructTypes();
4708 if (listStructDecl.contains(type))
4715 // Return a struct declaration
4716 private StructDecl getStructDecl(String type) {
4718 // Just iterate over the set of interfaces
4719 for (String intface : mapIntfacePTH.keySet()) {
4720 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4721 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4722 List<String> listStructDecl = structDecl.getStructTypes();
4723 if (listStructDecl.contains(type))
4730 // Return number of members (-1 if not found)
4731 private int getNumOfMembers(String type) {
4733 // Just iterate over the set of interfaces
4734 for (String intface : mapIntfacePTH.keySet()) {
4735 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4736 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4737 List<String> listStructDecl = structDecl.getStructTypes();
4738 if (listStructDecl.contains(type))
4739 return structDecl.getNumOfMembers(type);
4745 // Generate a set of classes for include statements
4746 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4748 Set<String> includeClasses = new HashSet<String>();
4749 for (String method : methods) {
4751 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4752 List<String> methParams = intDecl.getMethodParams(method);
4753 for (int i = 0; i < methPrmTypes.size(); i++) {
4755 String simpleType = getSimpleType(methPrmTypes.get(i));
4756 String param = methParams.get(i);
4757 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4758 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4759 } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4760 // For original interface, we need it exchanged... not for stub interfaces
4762 includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4763 includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\"");
4765 includeClasses.add("\"" + simpleType + ".hpp\"");
4766 includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\"");
4768 } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.ENUM) {
4769 includeClasses.add("\"" + simpleType + ".hpp\"");
4770 } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.STRUCT) {
4771 includeClasses.add("\"" + simpleType + ".hpp\"");
4772 } else if (param.contains("[]")) {
4773 // Check if this is array for C++; translate into vector
4774 includeClasses.add("<vector>");
4778 return includeClasses;
4782 // Generate a set of callback classes
4783 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4785 Set<String> callbackClasses = new HashSet<String>();
4786 for (String method : methods) {
4788 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4789 List<String> methParams = intDecl.getMethodParams(method);
4790 for (int i = 0; i < methPrmTypes.size(); i++) {
4792 String type = methPrmTypes.get(i);
4793 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4794 callbackClasses.add(type);
4795 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4796 // Can be a List<...> of callback objects ...
4797 String genericType = getTypeOfGeneric(type)[0];
4798 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4799 callbackClasses.add(type);
4804 return callbackClasses;
4808 // Print import statements into file
4809 private void printImportStatements(Collection<String> importClasses) {
4811 for(String cls : importClasses) {
4812 println("import " + cls + ";");
4817 // Print include statements into file
4818 private void printIncludeStatements(Collection<String> includeClasses) {
4820 for(String cls : includeClasses) {
4821 println("#include " + cls);
4826 // Get the C++ version of a non-primitive type
4827 // e.g. set for Set and map for Map
4828 // Input nonPrimitiveType has to be generics in format
4829 private String[] getTypeOfGeneric(String nonPrimitiveType) {
4831 // Handle <, >, and , for 2-type generic/template
4832 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
4837 // Gets generic type inside "<" and ">"
4838 private String getGenericType(String type) {
4840 // Handle <, >, and , for 2-type generic/template
4841 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4842 String[] substr = type.split("<")[1].split(">")[0].split(",");
4849 // This helper function strips off array declaration, e.g. int[] becomes int
4850 private String getSimpleArrayType(String type) {
4852 // Handle [ for array declaration
4853 String substr = type;
4854 if (type.contains("[]")) {
4855 substr = type.split("\\[\\]")[0];
4861 // This helper function strips off array declaration, e.g. D[] becomes D
4862 private String getSimpleIdentifier(String ident) {
4864 // Handle [ for array declaration
4865 String substr = ident;
4866 if (ident.contains("[]")) {
4867 substr = ident.split("\\[\\]")[0];
4873 // Checks and gets type in C++
4874 private String checkAndGetCplusType(String paramType) {
4876 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
4877 return convertType(paramType);
4878 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
4880 // Check for generic/template format
4881 if (paramType.contains("<") && paramType.contains(">")) {
4883 String genericClass = getSimpleType(paramType);
4884 String[] genericType = getTypeOfGeneric(paramType);
4885 String cplusTemplate = null;
4886 if (genericType.length == 1) // Generic/template with one type
4887 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
4888 "<" + convertType(genericType[0]) + ">";
4889 else // Generic/template with two types
4890 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
4891 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
4892 return cplusTemplate;
4894 return getNonPrimitiveCplusClass(paramType);
4895 } else if(paramType.contains("[]")) { // Array type (used for return type only)
4896 String cArray = "vector<" + getSimpleArrayType(paramType) + ">";
4898 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
4899 return paramType + "*";
4901 // Just return it as is if it's not non-primitives
4903 //return checkAndGetParamClass(paramType, true);
4907 // Detect array declaration, e.g. int A[],
4908 // then generate "int A[]" in C++ as "vector<int> A"
4909 private String checkAndGetCplusArray(String paramType, String param) {
4911 String paramComplete = null;
4912 // Check for array declaration
4913 if (param.contains("[]")) {
4914 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
4916 // Just return it as is if it's not an array
4917 paramComplete = paramType + " " + param;
4919 return paramComplete;
4923 // Detect array declaration, e.g. int A[],
4924 // then generate "int A[]" in C++ as "vector<int> A"
4925 // This method just returns the type
4926 private String checkAndGetCplusArrayType(String paramType) {
4928 String paramTypeRet = null;
4929 // Check for array declaration
4930 if (paramType.contains("[]")) {
4931 String type = paramType.split("\\[\\]")[0];
4932 paramTypeRet = checkAndGetCplusType(type) + "[]";
4933 } else if (paramType.contains("vector")) {
4934 // Just return it as is if it's not an array
4935 String type = paramType.split("<")[1].split(">")[0];
4936 paramTypeRet = checkAndGetCplusType(type) + "[]";
4938 paramTypeRet = paramType;
4940 return paramTypeRet;
4944 // Detect array declaration, e.g. int A[],
4945 // then generate "int A[]" in C++ as "vector<int> A"
4946 // This method just returns the type
4947 private String checkAndGetCplusArrayType(String paramType, String param) {
4949 String paramTypeRet = null;
4950 // Check for array declaration
4951 if (param.contains("[]")) {
4952 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
4953 } else if (paramType.contains("vector")) {
4954 // Just return it as is if it's not an array
4955 String type = paramType.split("<")[1].split(">")[0];
4956 paramTypeRet = checkAndGetCplusType(type) + "[]";
4958 paramTypeRet = paramType;
4960 return paramTypeRet;
4964 // Detect array declaration, e.g. int A[],
4965 // then generate type "int[]"
4966 private String checkAndGetArray(String paramType, String param) {
4968 String paramTypeRet = null;
4969 // Check for array declaration
4970 if (param.contains("[]")) {
4971 paramTypeRet = paramType + "[]";
4973 // Just return it as is if it's not an array
4974 paramTypeRet = paramType;
4976 return paramTypeRet;
4980 // Is array or list?
4981 private boolean isArrayOrList(String paramType, String param) {
4983 // Check for array declaration
4986 else if (isList(paramType))
4994 // For return type we use retType as input parameter
4995 private boolean isArray(String param) {
4997 // Check for array declaration
4998 if (param.contains("[]"))
5006 private boolean isList(String paramType) {
5008 // Check for array declaration
5009 if (paramType.contains("List"))
5016 // Get the right type for a callback object
5017 private String checkAndGetParamClass(String paramType) {
5019 // Check if this is generics
5020 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5021 return exchangeParamType(paramType);
5027 // Returns the other interface for type-checking purposes for USERDEFINED
5028 // classes based on the information provided in multiple policy files
5029 // e.g. return CameraWithXXX instead of Camera
5030 private String exchangeParamType(String intface) {
5032 // Param type that's passed is the interface name we need to look for
5033 // in the map of interfaces, based on available policy files.
5034 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5035 if (decHandler != null) {
5036 // We've found the required interface policy files
5037 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5038 Set<String> setExchInt = reqDecl.getInterfaces();
5039 if (setExchInt.size() == 1) {
5040 Iterator iter = setExchInt.iterator();
5041 return (String) iter.next();
5043 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5044 ". Only one new interface can be declared if the object " + intface +
5045 " needs to be passed in as an input parameter!");
5048 // NULL value - this means policy files missing
5049 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5050 "... Please provide the necessary policy files for user-defined types." +
5051 " If this is an array please type the brackets after the variable name," +
5052 " e.g. \"String str[]\", not \"String[] str\"." +
5053 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5054 " supports List/ArrayList (Java) or list (C++).");
5059 public static void main(String[] args) throws Exception {
5061 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5062 if ((args[0].equals("-help") ||
5063 args[0].equals("--help")||
5064 args[0].equals("-h")) ||
5065 (args.length == 0)) {
5067 IoTCompiler.printUsage();
5069 } else if (args.length > 1) {
5071 IoTCompiler comp = new IoTCompiler();
5074 // Parse main policy file
5075 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5076 // Parse "requires" policy file
5077 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5078 // Get interface name
5079 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5080 comp.setDataStructures(intface, pnPol, pnReq);
5081 comp.getMethodsForIntface(intface);
5083 // 1) Check if this is the last option before "-java" or "-cplus"
5084 // 2) Check if this is really the last option (no "-java" or "-cplus")
5085 } while(!args[i].equals("-java") &&
5086 !args[i].equals("-cplus") &&
5089 // Generate everything if we don't see "-java" or "-cplus"
5090 if (i == args.length) {
5091 comp.generateEnumJava();
5092 comp.generateStructJava();
5093 comp.generateJavaLocalInterfaces();
5094 comp.generateJavaInterfaces();
5095 comp.generateJavaStubClasses();
5096 comp.generateJavaCallbackStubClasses();
5097 comp.generateJavaSkeletonClass();
5098 comp.generateJavaCallbackSkeletonClass();
5099 comp.generateEnumCplus();
5100 comp.generateStructCplus();
5101 comp.generateCplusLocalInterfaces();
5102 comp.generateCPlusInterfaces();
5103 comp.generateCPlusStubClasses();
5104 comp.generateCPlusCallbackStubClasses();
5105 comp.generateCplusSkeletonClass();
5106 comp.generateCplusCallbackSkeletonClass();
5108 // Check other options
5109 while(i < args.length) {
5111 if (!args[i].equals("-java") &&
5112 !args[i].equals("-cplus")) {
5113 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
5115 if (i + 1 < args.length) {
5116 comp.setDirectory(args[i+1]);
5118 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
5120 if (args[i].equals("-java")) {
5121 comp.generateEnumJava();
5122 comp.generateStructJava();
5123 comp.generateJavaLocalInterfaces();
5124 comp.generateJavaInterfaces();
5125 comp.generateJavaStubClasses();
5126 comp.generateJavaCallbackStubClasses();
5127 comp.generateJavaSkeletonClass();
5128 comp.generateJavaCallbackSkeletonClass();
5130 comp.generateEnumCplus();
5131 comp.generateStructCplus();
5132 comp.generateCplusLocalInterfaces();
5133 comp.generateCPlusInterfaces();
5134 comp.generateCPlusStubClasses();
5135 comp.generateCPlusCallbackStubClasses();
5136 comp.generateCplusSkeletonClass();
5137 comp.generateCplusCallbackSkeletonClass();
5144 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5145 IoTCompiler.printUsage();
5146 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");