Adding policy dynamic checks on skeleton and stub that has callback objects
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
1 package iotpolicy;
2
3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
5 import java.io.*;
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;
14 import java.util.Map;
15 import java.util.Set;
16
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;
29
30 import iotrmi.Java.IoTRMITypes;
31
32
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.
37  *
38  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
39  * @version     1.0
40  * @since       2016-09-22
41  */
42 public class IoTCompiler {
43
44         /**
45          * Class properties
46          */
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;
59         private String dir;
60         private String subdir;
61
62         /**
63          * Class constants
64          */
65         private final static String OUTPUT_DIRECTORY = "output_files";
66
67         private enum ParamCategory {
68
69                 PRIMITIVES,             // All the primitive types, e.g. byte, short, int, long, etc.
70                 NONPRIMITIVES,  // Non-primitive types, e.g. Set, Map, List, etc.
71                 USERDEFINED             // Non-supported type by default; assumed as driver classes
72         }
73
74         /**
75          * Class constructors
76          */
77         public IoTCompiler() {
78
79                 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
80                 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
81                 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
82                 mapIntfaceObjId = new HashMap<String,Integer>();
83                 mapNewIntfaceObjId = new HashMap<String,Integer>();
84                 mapPrimitives = new HashMap<String,String>();
85                         arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
86                 mapNonPrimitivesJava = new HashMap<String,String>();
87                         arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
88                 mapNonPrimitivesCplus = new HashMap<String,String>();
89                         arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
90                 pw = null;
91                 dir = OUTPUT_DIRECTORY;
92                 subdir = null;
93         }
94
95
96         /**
97          * setDataStructures() sets parse tree and other data structures based on policy files.
98          * <p>
99          * It also generates parse tree (ParseTreeHandler) and
100          * copies useful information from parse tree into
101          * InterfaceDecl, CapabilityDecl, and RequiresDecl 
102          * data structures.
103          * Additionally, the data structure handles are
104          * returned from tree-parsing for further process.
105          *
106          */
107         public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
108
109                 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
110                 DeclarationHandler decHandler = new DeclarationHandler();
111                 // Process ParseNode and generate Declaration objects
112                 // Interface
113                 ptHandler.processInterfaceDecl();
114                 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
115                 decHandler.addInterfaceDecl(origInt, intDecl);
116                 // Capabilities
117                 ptHandler.processCapabilityDecl();
118                 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
119                 decHandler.addCapabilityDecl(origInt, capDecl);
120                 // Requires
121                 ptHandler.processRequiresDecl();
122                 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
123                 decHandler.addRequiresDecl(origInt, reqDecl);
124                 // Enumeration
125                 ptHandler.processEnumDecl();
126                 EnumDecl enumDecl = ptHandler.getEnumDecl();
127                 decHandler.addEnumDecl(origInt, enumDecl);
128                 // Struct
129                 ptHandler.processStructDecl();
130                 StructDecl structDecl = ptHandler.getStructDecl();
131                 decHandler.addStructDecl(origInt, structDecl);
132
133                 mapIntfacePTH.put(origInt, ptHandler);
134                 mapIntDeclHand.put(origInt, decHandler);
135                 // Set object Id counter to 0 for each interface
136                 mapIntfaceObjId.put(origInt, new Integer(0));
137         }
138
139
140         /**
141          * getMethodsForIntface() reads for methods in the data structure
142          * <p>
143          * It is going to give list of methods for a certain interface
144          *              based on the declaration of capabilities.
145          */
146         public void getMethodsForIntface(String origInt) {
147
148                 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
149                 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
150                 // Get set of new interfaces, e.g. CameraWithCaptureAndData
151                 // Generate this new interface with all the methods it needs
152                 //              from different capabilities it declares
153                 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
154                 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
155                 Set<String> setIntfaces = reqDecl.getInterfaces();
156                 for (String strInt : setIntfaces) {
157
158                         // Initialize a set of methods
159                         Set<String> setMethods = new HashSet<String>();
160                         // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
161                         List<String> listCapab = reqDecl.getCapabList(strInt);
162                         for (String strCap : listCapab) {
163
164                                 // Get list of methods for each capability
165                                 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
166                                 List<String> listCapabMeth = capDecl.getMethods(strCap);
167                                 for (String strMeth : listCapabMeth) {
168
169                                         // Add methods into setMethods
170                                         // This is to also handle redundancies (say two capabilities
171                                         //              share the same methods)
172                                         setMethods.add(strMeth);
173                                 }
174                         }
175                         // Add interface and methods information into map
176                         mapNewIntMethods.put(strInt, setMethods);
177                 }
178                 // Map the map of interface-methods to the original interface
179                 mapInt2NewInts.put(origInt, mapNewIntMethods);
180         }
181
182
183         /**
184          * HELPER: writeMethodJavaLocalInterface() writes the method of the interface
185          */
186         private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
187
188                 for (String method : methods) {
189
190                         List<String> methParams = intDecl.getMethodParams(method);
191                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
192                         print("public " + intDecl.getMethodType(method) + " " +
193                                 intDecl.getMethodId(method) + "(");
194                         for (int i = 0; i < methParams.size(); i++) {
195                                 // Check for params with driver class types and exchange it 
196                                 //              with its remote interface
197                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
198                                 print(paramType + " " + methParams.get(i));
199                                 // Check if this is the last element (don't print a comma)
200                                 if (i != methParams.size() - 1) {
201                                         print(", ");
202                                 }
203                         }
204                         println(");");
205                 }
206         }
207
208
209         /**
210          * HELPER: writeMethodJavaInterface() writes the method of the interface
211          */
212         private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
213
214                 for (String method : methods) {
215
216                         List<String> methParams = intDecl.getMethodParams(method);
217                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
218                         print("public " + intDecl.getMethodType(method) + " " +
219                                 intDecl.getMethodId(method) + "(");
220                         for (int i = 0; i < methParams.size(); i++) {
221                                 // Check for params with driver class types and exchange it 
222                                 //              with its remote interface
223                                 String paramType = methPrmTypes.get(i);
224                                 print(paramType + " " + methParams.get(i));
225                                 // Check if this is the last element (don't print a comma)
226                                 if (i != methParams.size() - 1) {
227                                         print(", ");
228                                 }
229                         }
230                         println(");");
231                 }
232         }
233
234
235         /**
236          * HELPER: writeEnumJava() writes the enumeration declaration
237          */
238         private void writeEnumJava(EnumDecl enumDecl) {
239
240                 Set<String> enumTypes = enumDecl.getEnumDeclarations();
241                 // Iterate over enum declarations
242                 for (String enType : enumTypes) {
243
244                         println("public enum " + enType + " {");
245                         List<String> enumMembers = enumDecl.getMembers(enType);
246                         for (int i = 0; i < enumMembers.size(); i++) {
247
248                                 String member = enumMembers.get(i);
249                                 print(member);
250                                 // Check if this is the last element (don't print a comma)
251                                 if (i != enumMembers.size() - 1)
252                                         println(",");
253                                 else
254                                         println("");
255                         }
256                         println("}\n");
257                 }
258         }
259
260
261         /**
262          * HELPER: writeStructJava() writes the struct declaration
263          */
264         private void writeStructJava(StructDecl structDecl) {
265
266                 List<String> structTypes = structDecl.getStructTypes();
267                 // Iterate over enum declarations
268                 for (String stType : structTypes) {
269
270                         println("public class " + stType + " {");
271                         List<String> structMemberTypes = structDecl.getMemberTypes(stType);
272                         List<String> structMembers = structDecl.getMembers(stType);
273                         for (int i = 0; i < structMembers.size(); i++) {
274
275                                 String memberType = structMemberTypes.get(i);
276                                 String member = structMembers.get(i);
277                                 println("public static " + memberType + " " + member + ";");
278                         }
279                         println("}\n");
280                 }
281         }
282
283
284         /**
285          * generateJavaLocalInterface() writes the local interface and provides type-checking.
286          * <p>
287          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
288          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
289          * The local interface has to be the input parameter for the stub and the stub 
290          * interface has to be the input parameter for the local class.
291          */
292         public void generateJavaLocalInterfaces() throws IOException {
293
294                 // Create a new directory
295                 createDirectory(dir);
296                 for (String intface : mapIntfacePTH.keySet()) {
297                         // Open a new file to write into
298                         FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
299                         pw = new PrintWriter(new BufferedWriter(fw));
300                         // Pass in set of methods and get import classes
301                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
302                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
303                         List<String> methods = intDecl.getMethods();
304                         Set<String> importClasses = getImportClasses(methods, intDecl);
305                         printImportStatements(importClasses);
306                         // Write interface header
307                         println("");
308                         println("public interface " + intface + " {");
309                         // Write enum if any...
310                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
311                         writeEnumJava(enumDecl);
312                         // Write struct if any...
313                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
314                         writeStructJava(structDecl);
315                         // Write methods
316                         writeMethodJavaLocalInterface(methods, intDecl);
317                         println("}");
318                         pw.close();
319                         System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
320                 }
321         }
322
323
324         /**
325          * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
326          */
327         public void generateJavaInterfaces() throws IOException {
328
329                 // Create a new directory
330                 String path = createDirectories(dir, subdir);
331                 for (String intface : mapIntfacePTH.keySet()) {
332
333                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
334                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
335
336                                 // Open a new file to write into
337                                 String newIntface = intMeth.getKey();
338                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
339                                 pw = new PrintWriter(new BufferedWriter(fw));
340                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
341                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
342                                 // Pass in set of methods and get import classes
343                                 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
344                                 printImportStatements(importClasses);
345                                 // Write interface header
346                                 println("");
347                                 println("public interface " + newIntface + " {\n");
348                                 // Write methods
349                                 writeMethodJavaInterface(intMeth.getValue(), intDecl);
350                                 println("}");
351                                 pw.close();
352                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
353                         }
354                 }
355         }
356
357
358         /**
359          * HELPER: writePropertiesJavaStub() writes the properties of the stub class
360          */
361         private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
362
363                 println("private IoTRMICall rmiCall;");
364                 println("private String address;");
365                 println("private int[] ports;\n");
366                 // Get the object Id
367                 Integer objId = mapIntfaceObjId.get(intface);
368                 println("private final static int objectId = " + objId + ";");
369                 mapNewIntfaceObjId.put(newIntface, objId);
370                 mapIntfaceObjId.put(intface, objId++);
371                 if (callbackExist) {
372                 // We assume that each class only has one callback interface for now
373                         Iterator it = callbackClasses.iterator();
374                         String callbackType = (String) it.next();
375                         println("// Callback properties");
376                         println("private IoTRMIObject rmiObj;");
377                         println("List<" + callbackType + "> listCallbackObj;");
378                         println("private static int objIdCnt = 0;");
379                         // Generate permission stuff for callback stubs
380                         DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
381                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
382                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(callbackType);
383                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
384                                 String newCallbackIntface = intMeth.getKey();
385                                 int newObjectId = mapNewIntfaceObjId.get(newCallbackIntface);
386                                 println("private final static int object" + newObjectId + "Id = " + 
387                                         newObjectId + ";\t//" + newCallbackIntface);
388                                 Set<String> methodIds = intMeth.getValue();
389                                 print("private static Integer[] object" + newObjectId + "Permission = { ");
390                                 int i = 0;
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) {
396                                                 print(", ");
397                                         }
398                                         i++;
399                                 }
400                                 println(" };");
401                                 println("private List<Integer> set" + newObjectId + "Allowed;");
402                         }
403                 }
404                 println("\n");
405         }
406
407
408         /**
409          * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
410          */
411         private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
412
413                 println("public " + newStubClass + "(int _port, String _address, int _rev, int[] _ports) throws Exception {");
414                 println("address = _address;");
415                 println("ports = _ports;");
416                 println("rmiCall = new IoTRMICall(_port, _address, _rev);");
417                 if (callbackExist) {
418                         Iterator it = callbackClasses.iterator();
419                         String callbackType = (String) it.next();
420                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
421                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
422                                 String newIntface = intMeth.getKey();
423                                 int newObjectId = mapNewIntfaceObjId.get(newIntface);
424                                 println("set" + newObjectId + "Allowed = Arrays.asList(object" + newObjectId +"Permission);");
425                         }
426                         println("listCallbackObj = new ArrayList<" + callbackType + ">();");
427                         println("___initCallBack();");
428                 }
429                 println("}\n");
430         }
431
432
433         /**
434          * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
435          */
436         private void writeJavaMethodCallbackPermission(String intface) {
437
438                 println("int methodId = IoTRMIObject.getMethodId(method);");
439                 // Get all the different stubs
440                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
441                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
442                         String newIntface = intMeth.getKey();
443                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
444                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
445                         println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
446                         println("}");
447                 }
448         }
449
450
451         /**
452          * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
453          */
454         private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl) {
455
456                 println("public void ___initCallBack() {");
457                 // Generate main thread for callbacks
458                 println("Thread thread = new Thread() {");
459                 println("public void run() {");
460                 println("try {");
461                 println("rmiObj = new IoTRMIObject(ports[0]);");
462                 println("while (true) {");
463                 println("byte[] method = rmiObj.getMethodBytes();");
464                 writeJavaMethodCallbackPermission(intface);
465                 println("int objId = IoTRMIObject.getObjectId(method);");
466                 println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);");
467                 println("if (skel != null) {");
468                 println("skel.invokeMethod(rmiObj);");
469                 println("} else {");
470                 println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");");
471                 println("}");
472                 println("}");
473                 println("} catch (Exception ex) {");
474                 println("ex.printStackTrace();");
475                 println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");");
476                 println("}");
477                 println("}");
478                 println("};");
479                 println("thread.start();\n");
480                 // Generate info sending part
481                 String method = "___initCallBack()";
482                 println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";");
483                 println("Class<?> retType = void.class;");
484                 println("Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };");
485                 println("Object[] paramObj = new Object[] { ports[0], address, 0 };");
486                 println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
487                 println("}\n");
488         }
489
490
491         /**
492          * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
493          */
494         private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
495                         List<String> methPrmTypes, String method) {
496
497                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
498                 String retType = intDecl.getMethodType(method);
499                 println("Class<?> retType = " + getSimpleType(retType) + ".class;");
500                 // Generate array of parameter types
501                 print("Class<?>[] paramCls = new Class<?>[] { ");
502                 for (int i = 0; i < methParams.size(); i++) {
503                         String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
504                         print(getSimpleType(paramType) + ".class");
505                         // Check if this is the last element (don't print a comma)
506                         if (i != methParams.size() - 1) {
507                                 print(", ");
508                         }
509                 }
510                 println(" };");
511                 // Generate array of parameter objects
512                 print("Object[] paramObj = new Object[] { ");
513                 for (int i = 0; i < methParams.size(); i++) {
514                         print(getSimpleIdentifier(methParams.get(i)));
515                         // Check if this is the last element (don't print a comma)
516                         if (i != methParams.size() - 1) {
517                                 print(", ");
518                         }
519                 }
520                 println(" };");
521                 // Check if this is "void"
522                 if (retType.equals("void")) {
523                         println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
524                 } else { // We do have a return value
525                 // Check if the return value NONPRIMITIVES
526                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
527                                 String[] retGenValType = getTypeOfGeneric(retType);
528                                 println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
529                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
530                                 println("return (" + retType + ")retObj;");
531                         } else {
532                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
533                                 println("return (" + retType + ")retObj;");
534                         }
535                 }
536         }
537
538
539         /**
540          * HELPER: returnGenericCallbackType() returns the callback type
541          */
542         private String returnGenericCallbackType(String paramType) {
543
544                 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
545                         return getTypeOfGeneric(paramType)[0];
546                 else
547                         return paramType;
548         }
549
550
551         /**
552          * HELPER: checkCallbackType() checks the callback type
553          */
554         private boolean checkCallbackType(String paramType, String callbackType) {
555
556                 String prmType = returnGenericCallbackType(paramType);
557                 return callbackType.equals(prmType);
558         }
559
560
561         /**
562          * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
563          */
564         private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
565                         List<String> methPrmTypes, String method, String callbackType) {
566
567                 println("try {");
568                 // Check if this is single object, array, or list of objects
569                 for (int i = 0; i < methParams.size(); i++) {
570
571                         String paramType = methPrmTypes.get(i);
572                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
573                                 String param = methParams.get(i);
574                                 if (isArrayOrList(paramType, param)) {  // Generate loop
575                                         println("for (" + paramType + " cb : " + getSimpleIdentifier(param) + ") {");
576                                         println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
577                                 } else
578                                         println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(" +
579                                                 getSimpleIdentifier(param) + ", objIdCnt++);");
580                                 println("listCallbackObj.add(skel);");
581                                 if (isArrayOrList(paramType, param))
582                                         println("}");
583                         }
584                 }
585                 println("} catch (Exception ex) {");
586                 println("ex.printStackTrace();");
587                 println("throw new Error(\"Exception when generating skeleton objects!\");");
588                 println("}\n");
589                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
590                 String retType = intDecl.getMethodType(method);
591                 println("Class<?> retType = " + getSimpleType(retType) + ".class;");
592                 // Generate array of parameter types
593                 print("Class<?>[] paramCls = new Class<?>[] { ");
594                 for (int i = 0; i < methParams.size(); i++) {
595                         String paramType = methPrmTypes.get(i);
596                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
597                                 print("int.class");
598                         } else { // Generate normal classes if it's not a callback object
599                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
600                                 print(getSimpleType(prmType) + ".class");
601                         }
602                         if (i != methParams.size() - 1) // Check if this is the last element
603                                 print(", ");
604                 }
605                 println(" };");
606                 // Generate array of parameter objects
607                 print("Object[] paramObj = new Object[] { ");
608                 for (int i = 0; i < methParams.size(); i++) {
609                         String paramType = methPrmTypes.get(i);
610                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
611                                 if (isArray(methPrmTypes.get(i), methParams.get(i)))
612                                         print(getSimpleIdentifier(methParams.get(i)) + ".length");
613                                 else if (isList(methPrmTypes.get(i), methParams.get(i)))
614                                         print(getSimpleIdentifier(methParams.get(i)) + ".size()");
615                                 else
616                                         print("new Integer(1)");
617                         } else
618                                 print(getSimpleIdentifier(methParams.get(i)));
619                         if (i != methParams.size() - 1)
620                                 print(", ");
621                 }
622                 println(" };");
623                 // Check if this is "void"
624                 if (retType.equals("void")) {
625                         println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
626                 } else { // We do have a return value
627                 // Check if the return value NONPRIMITIVES
628                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
629                                 String[] retGenValType = getTypeOfGeneric(retType);
630                                 println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
631                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
632                                 println("return (" + retType + ")retObj;");
633                         } else {
634                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
635                                 println("return (" + retType + ")retObj;");
636                         }
637                 }
638         }
639
640
641         /**
642          * HELPER: writeMethodJavaStub() writes the method of the stub class
643          */
644         private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
645
646                 for (String method : methods) {
647
648                         List<String> methParams = intDecl.getMethodParams(method);
649                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
650                         print("public " + intDecl.getMethodType(method) + " " +
651                                 intDecl.getMethodId(method) + "(");
652                         boolean isCallbackMethod = false;
653                         String callbackType = null;
654                         for (int i = 0; i < methParams.size(); i++) {
655
656                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
657                                 // Check if this has callback object
658                                 if (callbackClasses.contains(paramType)) {
659                                         isCallbackMethod = true;
660                                         callbackType = paramType;       
661                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
662                                 }
663                                 print(methPrmTypes.get(i) + " " + methParams.get(i));
664                                 // Check if this is the last element (don't print a comma)
665                                 if (i != methParams.size() - 1) {
666                                         print(", ");
667                                 }
668                         }
669                         println(") {");
670                         // Now, write the body of stub!
671                         if (isCallbackMethod)
672                                 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
673                         else
674                                 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method);
675                         println("}\n");
676                         // Write the init callback helper method
677                         if (isCallbackMethod)
678                                 writeInitCallbackJavaStub(callbackType, intDecl);
679                 }
680         }
681
682
683         /**
684          * generateJavaStubClasses() generate stubs based on the methods list in Java
685          */
686         public void generateJavaStubClasses() throws IOException {
687
688                 // Create a new directory
689                 String path = createDirectories(dir, subdir);
690                 for (String intface : mapIntfacePTH.keySet()) {
691
692                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
693                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
694
695                                 // Open a new file to write into
696                                 String newIntface = intMeth.getKey();
697                                 String newStubClass = newIntface + "_Stub";
698                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
699                                 pw = new PrintWriter(new BufferedWriter(fw));
700                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
701                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
702                                 // Pass in set of methods and get import classes
703                                 Set<String> methods = intMeth.getValue();
704                                 Set<String> importClasses = getImportClasses(methods, intDecl);
705                                 List<String> stdImportClasses = getStandardJavaImportClasses();
706                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
707                                 printImportStatements(allImportClasses); println("");
708                                 // Find out if there are callback objects
709                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
710                                 boolean callbackExist = !callbackClasses.isEmpty();
711                                 // Write class header
712                                 println("public class " + newStubClass + " implements " + newIntface + " {\n");
713                                 // Write properties
714                                 writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses);
715                                 // Write constructor
716                                 writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses);
717                                 // Write methods
718                                 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
719                                 println("}");
720                                 pw.close();
721                                 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
722                         }
723                 }
724         }
725
726
727         /**
728          * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class
729          */
730         private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
731
732                 println("private IoTRMICall rmiCall;");
733                 println("private String address;");
734                 println("private int[] ports;\n");
735                 // Get the object Id
736                 println("private static int objectId = 0;");
737                 if (callbackExist) {
738                 // We assume that each class only has one callback interface for now
739                         Iterator it = callbackClasses.iterator();
740                         String callbackType = (String) it.next();
741                         println("// Callback properties");
742                         println("private IoTRMIObject rmiObj;");
743                         println("List<" + callbackType + "> listCallbackObj;");
744                         println("private static int objIdCnt = 0;");
745                         // Generate permission stuff for callback stubs
746                         DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
747                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
748                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(callbackType);
749                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
750                                 String newCallbackIntface = intMeth.getKey();
751                                 int newObjectId = mapNewIntfaceObjId.get(newCallbackIntface);
752                                 println("private final static int object" + newObjectId + "Id = " + 
753                                         newObjectId + ";\t//" + newCallbackIntface);
754                                 Set<String> methodIds = intMeth.getValue();
755                                 print("private static Integer[] object" + newObjectId + "Permission = { ");
756                                 int i = 0;
757                                 for (String methodId : methodIds) {
758                                         int methodNumId = intDecl.getMethodNumId(methodId);
759                                         print(Integer.toString(methodNumId));
760                                         // Check if this is the last element (don't print a comma)
761                                         if (i != methodIds.size() - 1) {
762                                                 print(", ");
763                                         }
764                                         i++;
765                                 }
766                                 println(" };");
767                                 println("private List<Integer> set" + newObjectId + "Allowed;");
768                         }
769                 }
770                 println("\n");
771         }
772
773
774         /**
775          * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class
776          */
777         private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
778
779                 // TODO: If we want callback in callback, then we need to add address and port initializations
780                 println("public " + newStubClass + "(IoTRMICall _rmiCall, int _objectId) throws Exception {");
781                 println("objectId = _objectId;");
782                 println("rmiCall = _rmiCall;");
783                 if (callbackExist) {
784                         Iterator it = callbackClasses.iterator();
785                         String callbackType = (String) it.next();
786                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
787                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
788                                 String newIntface = intMeth.getKey();
789                                 int newObjectId = mapNewIntfaceObjId.get(newIntface);
790                                 println("set" + newObjectId + "Allowed = Arrays.asList(object" + newObjectId +"Permission);");
791                         }
792                         println("listCallbackObj = new ArrayList<" + callbackType + ">();");
793                         println("___initCallBack();");
794                         println("// TODO: Add address and port initialization here if we want callback in callback!");
795                 }
796                 println("}\n");
797         }
798
799
800         /**
801          * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java
802          * <p>
803          * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input
804          * because all these stubs are populated by the class that takes in this object as a callback
805          * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects.
806          */
807         public void generateJavaCallbackStubClasses() throws IOException {
808
809                 // Create a new directory
810                 String path = createDirectories(dir, subdir);
811                 for (String intface : mapIntfacePTH.keySet()) {
812
813                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
814                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
815
816                                 // Open a new file to write into
817                                 String newIntface = intMeth.getKey();
818                                 String newStubClass = newIntface + "_CallbackStub";
819                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
820                                 pw = new PrintWriter(new BufferedWriter(fw));
821                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
822                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
823                                 // Pass in set of methods and get import classes
824                                 Set<String> methods = intMeth.getValue();
825                                 Set<String> importClasses = getImportClasses(methods, intDecl);
826                                 List<String> stdImportClasses = getStandardJavaImportClasses();
827                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
828                                 printImportStatements(allImportClasses); println("");
829                                 // Find out if there are callback objects
830                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
831                                 boolean callbackExist = !callbackClasses.isEmpty();
832                                 // Write class header
833                                 println("public class " + newStubClass + " implements " + newIntface + " {\n");
834                                 // Write properties
835                                 writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses);
836                                 // Write constructor
837                                 writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses);
838                                 // Write methods
839                                 // TODO: perhaps need to generate callback for callback
840                                 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
841                                 println("}");
842                                 pw.close();
843                                 System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java...");
844                         }
845                 }
846         }
847
848
849         /**
850          * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
851          */
852         private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) {
853
854                 println("private " + intface + " mainObj;");
855                 //println("private int ports;");
856                 println("private IoTRMIObject rmiObj;\n");
857                 // Callback
858                 if (callbackExist) {
859                         println("private static int objIdCnt = 0;");
860                         println("private IoTRMICall rmiCall;");
861                 }
862                 // Keep track of object Ids of all stubs registered to this interface
863                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
864                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
865                         String newIntface = intMeth.getKey();
866                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
867                         println("private final static int object" + newObjectId + "Id = " + 
868                                 newObjectId + ";\t//" + newIntface);
869                         Set<String> methodIds = intMeth.getValue();
870                         print("private static Integer[] object" + newObjectId + "Permission = { ");
871                         int i = 0;
872                         for (String methodId : methodIds) {
873                                 int methodNumId = intDecl.getMethodNumId(methodId);
874                                 print(Integer.toString(methodNumId));
875                                 // Check if this is the last element (don't print a comma)
876                                 if (i != methodIds.size() - 1) {
877                                         print(", ");
878                                 }
879                                 i++;
880                         }
881                         println(" };");
882                         println("private List<Integer> set" + newObjectId + "Allowed;");
883                 }
884                 println("\n");
885         }
886
887
888         /**
889          * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
890          */
891         private void writeConstructorJavaSkeleton(String newSkelClass, String intface) {
892
893                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _port) throws Exception {");
894                 println("mainObj = _mainObj;");
895                 println("rmiObj = new IoTRMIObject(_port);");
896                 // Generate permission control initialization
897                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
898                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
899                         String newIntface = intMeth.getKey();
900                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
901                         println("set" + newObjectId + "Allowed = Arrays.asList(object" + newObjectId +"Permission);");
902                 }
903                 println("___waitRequestInvokeMethod();");
904                 println("}\n");
905         }
906
907
908         /**
909          * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
910          */
911         private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
912
913                 if (methodType.equals("void"))
914                         print("mainObj." + methodId + "(");
915                 else
916                         print("return mainObj." + methodId + "(");
917                 for (int i = 0; i < methParams.size(); i++) {
918
919                         print(getSimpleIdentifier(methParams.get(i)));
920                         // Check if this is the last element (don't print a comma)
921                         if (i != methParams.size() - 1) {
922                                 print(", ");
923                         }
924                 }
925                 println(");");
926         }
927
928
929         /**
930          * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class
931          */
932         private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton) {
933
934                 // This is a callback skeleton generation
935                 if (callbackSkeleton)
936                         println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {");
937                 else
938                         println("public void ___regCB() throws IOException {");
939                 println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, String.class, int.class },");
940                 println("\tnew Class<?>[] { null, null, null });");
941                 println("rmiCall = new IoTRMICall((int) paramObj[0], (String) paramObj[1], (int) paramObj[2]);");
942                 println("}\n");
943         }
944
945
946         /**
947          * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
948          */
949         private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, 
950                         boolean callbackSkeleton) {
951
952                 for (String method : methods) {
953
954                         List<String> methParams = intDecl.getMethodParams(method);
955                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
956                         String methodId = intDecl.getMethodId(method);
957                         print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
958                         boolean isCallbackMethod = false;
959                         String callbackType = null;
960                         for (int i = 0; i < methParams.size(); i++) {
961
962                                 String origParamType = methPrmTypes.get(i);
963                                 String paramType = checkAndGetParamClass(origParamType);
964                                 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
965                                         isCallbackMethod = true;
966                                         callbackType = origParamType;   
967                                 }
968                                 print(paramType + " " + methParams.get(i));
969                                 // Check if this is the last element (don't print a comma)
970                                 if (i != methParams.size() - 1) {
971                                         print(", ");
972                                 }
973                         }
974                         println(") {");
975                         // Now, write the body of skeleton!
976                         writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
977                         println("}\n");
978                         if (isCallbackMethod)
979                                 writeInitCallbackJavaSkeleton(callbackSkeleton);
980                 }
981         }
982
983
984         /**
985          * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
986          */
987         private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
988
989                 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
990                 // Iterate over callback objects
991                 for (int i = 0; i < methParams.size(); i++) {
992                         String paramType = methPrmTypes.get(i);
993                         String param = methParams.get(i);
994                         //if (callbackType.equals(paramType)) {
995                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
996                                 println("try {");
997                                 String exchParamType = checkAndGetParamClass(paramType);
998                                 // Print array if this is array or list if this is a list of callback objects
999                                 if (isArray(paramType, param)) {
1000                                         println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1001                                         println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1002                                 } else if (isList(paramType, param)) {
1003                                         println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1004                                         println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1005                                 } else {
1006                                         println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1007                                         println("objIdCnt++;");
1008                                 }
1009                         }
1010                         // Generate a loop if needed
1011                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1012                                 String exchParamType = checkAndGetParamClass(paramType);
1013                                 if (isArray(paramType, param)) {
1014                                         println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1015                                         println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1016                                         println("objIdCnt++;");
1017                                         println("}");
1018                                 } else if (isList(paramType, param)) {
1019                                         println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1020                                         println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt));");
1021                                         println("objIdCnt++;");
1022                                         println("}");
1023                                 }
1024                                 mapStubParam.put(i, "stub" + i);        // List of all stub parameters
1025                         }
1026                 }
1027                 return mapStubParam;
1028         }
1029
1030
1031         /**
1032          * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1033          */
1034         private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1035                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1036                 // Generate array of parameter objects
1037                 boolean isCallbackMethod = false;
1038                 String callbackType = null;
1039                 print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { ");
1040                 for (int i = 0; i < methParams.size(); i++) {
1041
1042                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1043                         if (callbackClasses.contains(paramType)) {
1044                                 isCallbackMethod = true;
1045                                 callbackType = paramType;
1046                                 print("int.class");
1047                         } else {        // Generate normal classes if it's not a callback object
1048                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1049                                 print(getSimpleType(prmType) + ".class");
1050                         }
1051                         if (i != methParams.size() - 1)
1052                                 print(", ");
1053                 }
1054                 println(" }, ");
1055                 // Generate generic class if it's a generic type.. null otherwise
1056                 print("new Class<?>[] { ");
1057                 for (int i = 0; i < methParams.size(); i++) {
1058                         String prmType = methPrmTypes.get(i);
1059                         if (getParamCategory(prmType) == ParamCategory.NONPRIMITIVES)
1060                                 print(getTypeOfGeneric(prmType)[0] + ".class");
1061                         else
1062                                 print("null");
1063                         if (i != methParams.size() - 1)
1064                                 print(", ");
1065                 }
1066                 println(" });");
1067                 Map<Integer,String> mapStubParam = null;
1068                 if (isCallbackMethod)
1069                         mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType);
1070                 // Check if this is "void"
1071                 String retType = intDecl.getMethodType(method);
1072                 if (retType.equals("void")) {
1073                         print(intDecl.getMethodId(method) + "(");
1074                 } else { // We do have a return value
1075                         print("Object retObj = " + intDecl.getMethodId(method) + "(");
1076                 }
1077                 for (int i = 0; i < methParams.size(); i++) {
1078
1079                         if (isCallbackMethod) {
1080                                 print(mapStubParam.get(i));     // Get the callback parameter
1081                         } else {
1082                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1083                                 print("(" + prmType + ") paramObj[" + i + "]");
1084                         }
1085                         if (i != methParams.size() - 1)
1086                                 print(", ");
1087                 }
1088                 println(");");
1089                 if (!retType.equals("void"))
1090                         println("rmiObj.sendReturnObj(retObj);");
1091                 if (isCallbackMethod) { // Catch exception if this is callback
1092                         println("} catch(Exception ex) {");
1093                         println("ex.printStackTrace();");
1094                         println("throw new Error(\"Exception from callback object instantiation!\");");
1095                         println("}");
1096                 }
1097         }
1098
1099
1100         /**
1101          * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1102          */
1103         private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1104
1105                 // Use this set to handle two same methodIds
1106                 Set<String> uniqueMethodIds = new HashSet<String>();
1107                 for (String method : methods) {
1108
1109                         List<String> methParams = intDecl.getMethodParams(method);
1110                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1111                         String methodId = intDecl.getMethodId(method);
1112                         print("public void ___");
1113                         String helperMethod = methodId;
1114                         if (uniqueMethodIds.contains(methodId))
1115                                 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1116                         else
1117                                 uniqueMethodIds.add(methodId);
1118                         // Check if this is "void"
1119                         String retType = intDecl.getMethodType(method);
1120                         if (retType.equals("void"))
1121                                 println(helperMethod + "() {");
1122                         else
1123                                 println(helperMethod + "() throws IOException {");
1124                         // Now, write the helper body of skeleton!
1125                         writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1126                         println("}\n");
1127                 }
1128         }
1129
1130
1131         /**
1132          * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
1133          */
1134         private void writeJavaMethodPermission(String intface) {
1135
1136                 // Get all the different stubs
1137                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1138                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1139                         String newIntface = intMeth.getKey();
1140                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
1141                         println("if (_objectId == object" + newObjectId + "Id) {");
1142                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
1143                         println("throw new Error(\"Object with object Id: \" + _objectId + \"  is not allowed to access method: \" + methodId);");
1144                         println("}");
1145                         println("else {");
1146                         println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");");
1147                         println("}");
1148                         println("}");
1149                 }
1150         }
1151
1152
1153         /**
1154          * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
1155          */
1156         private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
1157
1158                 // Use this set to handle two same methodIds
1159                 Set<String> uniqueMethodIds = new HashSet<String>();
1160                 println("private void ___waitRequestInvokeMethod() throws IOException {");
1161                 // Write variables here if we have callbacks or enums or structs
1162                 println("while (true) {");
1163                 println("rmiObj.getMethodBytes();");
1164                 println("int _objectId = rmiObj.getObjectId();");
1165                 println("int methodId = rmiObj.getMethodId();");
1166                 // Generate permission check
1167                 writeJavaMethodPermission(intface);
1168                 println("switch (methodId) {");
1169                 // Print methods and method Ids
1170                 for (String method : methods) {
1171                         String methodId = intDecl.getMethodId(method);
1172                         int methodNumId = intDecl.getMethodNumId(method);
1173                         print("case " + methodNumId + ": ___");
1174                         String helperMethod = methodId;
1175                         if (uniqueMethodIds.contains(methodId))
1176                                 helperMethod = helperMethod + methodNumId;
1177                         else
1178                                 uniqueMethodIds.add(methodId);
1179                         println(helperMethod + "(); break;");
1180                 }
1181                 String method = "___initCallBack()";
1182                 // Print case -9999 (callback handler) if callback exists
1183                 if (callbackExist) {
1184                         int methodId = intDecl.getHelperMethodNumId(method);
1185                         println("case " + methodId + ": ___regCB(); break;");
1186                 }
1187                 println("default: ");
1188                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
1189                 println("}");
1190                 println("}");
1191                 println("}\n");
1192         }
1193
1194
1195         /**
1196          * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
1197          */
1198         public void generateJavaSkeletonClass() throws IOException {
1199
1200                 // Create a new directory
1201                 String path = createDirectories(dir, subdir);
1202                 for (String intface : mapIntfacePTH.keySet()) {
1203                         // Open a new file to write into
1204                         String newSkelClass = intface + "_Skeleton";
1205                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
1206                         pw = new PrintWriter(new BufferedWriter(fw));
1207                         // Pass in set of methods and get import classes
1208                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1209                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1210                         List<String> methods = intDecl.getMethods();
1211                         Set<String> importClasses = getImportClasses(methods, intDecl);
1212                         List<String> stdImportClasses = getStandardJavaImportClasses();
1213                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1214                         printImportStatements(allImportClasses);
1215                         // Find out if there are callback objects
1216                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1217                         boolean callbackExist = !callbackClasses.isEmpty();
1218                         // Write class header
1219                         println("");
1220                         println("public class " + newSkelClass  + " implements " + intface + " {\n");
1221                         // Write properties
1222                         writePropertiesJavaSkeleton(intface, callbackExist, intDecl);
1223                         // Write constructor
1224                         writeConstructorJavaSkeleton(newSkelClass, intface);
1225                         // Write methods
1226                         writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false);
1227                         // Write method helper
1228                         writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
1229                         // Write waitRequestInvokeMethod() - main loop
1230                         writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
1231                         println("}");
1232                         pw.close();
1233                         System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
1234                 }
1235         }
1236
1237
1238         /**
1239          * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class
1240          */
1241         private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) {
1242
1243                 println("private " + intface + " mainObj;");
1244                 // For callback skeletons, this is its own object Id
1245                 println("private static int objectId = 0;");
1246                 // Callback
1247                 if (callbackExist) {
1248                         println("private static int objIdCnt = 0;");
1249                         println("private IoTRMICall rmiCall;");
1250                 }
1251                 println("\n");
1252         }
1253
1254
1255         /**
1256          * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class
1257          */
1258         private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface) {
1259
1260                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _objectId) throws Exception {");
1261                 println("mainObj = _mainObj;");
1262                 println("objectId = _objectId;");
1263                 println("}\n");
1264         }
1265
1266
1267         /**
1268          * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class
1269          */
1270         private void writeMethodHelperJavaCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1271
1272                 // Use this set to handle two same methodIds
1273                 Set<String> uniqueMethodIds = new HashSet<String>();
1274                 for (String method : methods) {
1275
1276                         List<String> methParams = intDecl.getMethodParams(method);
1277                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1278                         String methodId = intDecl.getMethodId(method);
1279                         print("public void ___");
1280                         String helperMethod = methodId;
1281                         if (uniqueMethodIds.contains(methodId))
1282                                 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1283                         else
1284                                 uniqueMethodIds.add(methodId);
1285                         // Check if this is "void"
1286                         String retType = intDecl.getMethodType(method);
1287                         if (retType.equals("void"))
1288                                 println(helperMethod + "(IoTRMIObject rmiObj) {");
1289                         else
1290                                 println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {");
1291                         // Now, write the helper body of skeleton!
1292                         writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1293                         println("}\n");
1294                 }
1295         }
1296
1297
1298         /**
1299          * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class
1300          */
1301         private void writeJavaCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
1302
1303                 // Use this set to handle two same methodIds
1304                 Set<String> uniqueMethodIds = new HashSet<String>();
1305                 println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {");
1306                 // Write variables here if we have callbacks or enums or structs
1307                 println("int methodId = rmiObj.getMethodId();");
1308                 // TODO: code the permission check here!
1309                 println("switch (methodId) {");
1310                 // Print methods and method Ids
1311                 for (String method : methods) {
1312                         String methodId = intDecl.getMethodId(method);
1313                         int methodNumId = intDecl.getMethodNumId(method);
1314                         print("case " + methodNumId + ": ___");
1315                         String helperMethod = methodId;
1316                         if (uniqueMethodIds.contains(methodId))
1317                                 helperMethod = helperMethod + methodNumId;
1318                         else
1319                                 uniqueMethodIds.add(methodId);
1320                         println(helperMethod + "(rmiObj); break;");
1321                 }
1322                 String method = "___initCallBack()";
1323                 // Print case -9999 (callback handler) if callback exists
1324                 if (callbackExist) {
1325                         int methodId = intDecl.getHelperMethodNumId(method);
1326                         println("case " + methodId + ": ___regCB(rmiObj); break;");
1327                 }
1328                 println("default: ");
1329                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
1330                 println("}");
1331                 println("}\n");
1332         }
1333
1334
1335         /**
1336          * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java
1337          */
1338         public void generateJavaCallbackSkeletonClass() throws IOException {
1339
1340                 // Create a new directory
1341                 String path = createDirectories(dir, subdir);
1342                 for (String intface : mapIntfacePTH.keySet()) {
1343                         // Open a new file to write into
1344                         String newSkelClass = intface + "_CallbackSkeleton";
1345                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
1346                         pw = new PrintWriter(new BufferedWriter(fw));
1347                         // Pass in set of methods and get import classes
1348                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1349                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1350                         List<String> methods = intDecl.getMethods();
1351                         Set<String> importClasses = getImportClasses(methods, intDecl);
1352                         List<String> stdImportClasses = getStandardJavaImportClasses();
1353                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1354                         printImportStatements(allImportClasses);
1355                         // Find out if there are callback objects
1356                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1357                         boolean callbackExist = !callbackClasses.isEmpty();
1358                         // Write class header
1359                         println("");
1360                         println("public class " + newSkelClass  + " implements " + intface + " {\n");
1361                         // Write properties
1362                         writePropertiesJavaCallbackSkeleton(intface, callbackExist);
1363                         // Write constructor
1364                         writeConstructorJavaCallbackSkeleton(newSkelClass, intface);
1365                         // Write methods
1366                         writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true);
1367                         // Write method helper
1368                         writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses);
1369                         // Write waitRequestInvokeMethod() - main loop
1370                         writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
1371                         println("}");
1372                         pw.close();
1373                         System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java...");
1374                 }
1375         }
1376
1377
1378         /**
1379          * HELPER: writeMethodCplusLocalInterface() writes the method of the interface
1380          */
1381         private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
1382
1383                 for (String method : methods) {
1384
1385                         List<String> methParams = intDecl.getMethodParams(method);
1386                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1387                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
1388                                 intDecl.getMethodId(method) + "(");
1389                         for (int i = 0; i < methParams.size(); i++) {
1390                                 // Check for params with driver class types and exchange it 
1391                                 //              with its remote interface
1392                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
1393                                 paramType = checkAndGetCplusType(paramType);
1394                                 // Check for arrays - translate into vector in C++
1395                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
1396                                 print(paramComplete);
1397                                 // Check if this is the last element (don't print a comma)
1398                                 if (i != methParams.size() - 1) {
1399                                         print(", ");
1400                                 }
1401                         }
1402                         println(") = 0;");
1403                 }
1404         }
1405
1406
1407         /**
1408          * HELPER: writeMethodCplusInterface() writes the method of the interface
1409          */
1410         private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
1411
1412                 for (String method : methods) {
1413
1414                         List<String> methParams = intDecl.getMethodParams(method);
1415                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1416                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
1417                                 intDecl.getMethodId(method) + "(");
1418                         for (int i = 0; i < methParams.size(); i++) {
1419                                 // Check for params with driver class types and exchange it 
1420                                 //              with its remote interface
1421                                 String paramType = methPrmTypes.get(i);
1422                                 paramType = checkAndGetCplusType(paramType);
1423                                 // Check for arrays - translate into vector in C++
1424                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
1425                                 print(paramComplete);
1426                                 // Check if this is the last element (don't print a comma)
1427                                 if (i != methParams.size() - 1) {
1428                                         print(", ");
1429                                 }
1430                         }
1431                         println(") = 0;");
1432                 }
1433         }
1434
1435
1436         /**
1437          * HELPER: writeEnumCplus() writes the enumeration declaration
1438          */
1439         private void writeEnumCplus(EnumDecl enumDecl) {
1440
1441                 Set<String> enumTypes = enumDecl.getEnumDeclarations();
1442                 // Iterate over enum declarations
1443                 for (String enType : enumTypes) {
1444
1445                         println("enum " + enType + " {");
1446                         List<String> enumMembers = enumDecl.getMembers(enType);
1447                         for (int i = 0; i < enumMembers.size(); i++) {
1448
1449                                 String member = enumMembers.get(i);
1450                                 print(member);
1451                                 // Check if this is the last element (don't print a comma)
1452                                 if (i != enumMembers.size() - 1)
1453                                         println(",");
1454                                 else
1455                                         println("");
1456                         }
1457                         println("};\n");
1458                 }
1459         }
1460
1461
1462         /**
1463          * HELPER: writeStructCplus() writes the struct declaration
1464          */
1465         private void writeStructCplus(StructDecl structDecl) {
1466
1467                 List<String> structTypes = structDecl.getStructTypes();
1468                 // Iterate over enum declarations
1469                 for (String stType : structTypes) {
1470
1471                         println("struct " + stType + " {");
1472                         List<String> structMemberTypes = structDecl.getMemberTypes(stType);
1473                         List<String> structMembers = structDecl.getMembers(stType);
1474                         for (int i = 0; i < structMembers.size(); i++) {
1475
1476                                 String memberType = structMemberTypes.get(i);
1477                                 String member = structMembers.get(i);
1478                                 String structTypeC = checkAndGetCplusType(memberType);
1479                                 String structComplete = checkAndGetCplusArray(structTypeC, member);
1480                                 println(structComplete + ";");
1481                         }
1482                         println("};\n");
1483                 }
1484         }
1485
1486
1487         /**
1488          * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
1489          * <p>
1490          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
1491          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
1492          * The local interface has to be the input parameter for the stub and the stub 
1493          * interface has to be the input parameter for the local class.
1494          */
1495         public void generateCplusLocalInterfaces() throws IOException {
1496
1497                 // Create a new directory
1498                 createDirectory(dir);
1499                 for (String intface : mapIntfacePTH.keySet()) {
1500                         // Open a new file to write into
1501                         FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
1502                         pw = new PrintWriter(new BufferedWriter(fw));
1503                         // Write file headers
1504                         println("#ifndef _" + intface.toUpperCase() + "_HPP__");
1505                         println("#define _" + intface.toUpperCase() + "_HPP__");
1506                         println("#include <iostream>");
1507                         // Pass in set of methods and get include classes
1508                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1509                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1510                         List<String> methods = intDecl.getMethods();
1511                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, true);
1512                         printIncludeStatements(includeClasses); println("");
1513                         println("using namespace std;\n");
1514                         // Write enum if any...
1515                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
1516                         writeEnumCplus(enumDecl);
1517                         // Write struct if any...
1518                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
1519                         writeStructCplus(structDecl);
1520                         println("class " + intface); println("{");
1521                         println("public:");
1522                         // Write methods
1523                         writeMethodCplusLocalInterface(methods, intDecl);
1524                         println("};");
1525                         println("#endif");
1526                         pw.close();
1527                         System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
1528                 }
1529         }
1530
1531
1532         /**
1533          * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
1534          * <p>
1535          * For C++ we use virtual classe as interface
1536          */
1537         public void generateCPlusInterfaces() throws IOException {
1538
1539                 // Create a new directory
1540                 String path = createDirectories(dir, subdir);
1541                 for (String intface : mapIntfacePTH.keySet()) {
1542
1543                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1544                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1545
1546                                 // Open a new file to write into
1547                                 String newIntface = intMeth.getKey();
1548                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
1549                                 pw = new PrintWriter(new BufferedWriter(fw));
1550                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1551                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1552                                 // Write file headers
1553                                 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
1554                                 println("#define _" + newIntface.toUpperCase() + "_HPP__");
1555                                 println("#include <iostream>");
1556                                 // Pass in set of methods and get import classes
1557                                 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl, false);
1558                                 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
1559                                 List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
1560                                 printIncludeStatements(allIncludeClasses); println("");                 
1561                                 println("using namespace std;\n");
1562                                 println("class " + newIntface);
1563                                 println("{");
1564                                 println("public:");
1565                                 // Write methods
1566                                 writeMethodCplusInterface(intMeth.getValue(), intDecl);
1567                                 println("};");
1568                                 println("#endif");
1569                                 pw.close();
1570                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
1571                         }
1572                 }
1573         }
1574
1575
1576         /**
1577          * HELPER: writeMethodCplusStub() writes the method of the stub
1578          */
1579         private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1580
1581                 for (String method : methods) {
1582
1583                         List<String> methParams = intDecl.getMethodParams(method);
1584                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1585                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
1586                                 intDecl.getMethodId(method) + "(");
1587                         boolean isCallbackMethod = false;
1588                         String callbackType = null;
1589                         for (int i = 0; i < methParams.size(); i++) {
1590
1591                                 String paramType = methPrmTypes.get(i);
1592                                 // Check if this has callback object
1593                                 if (callbackClasses.contains(paramType)) {
1594                                         isCallbackMethod = true;
1595                                         callbackType = paramType;       
1596                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
1597                                 }
1598                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
1599                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
1600                                 print(methParamComplete);
1601                                 // Check if this is the last element (don't print a comma)
1602                                 if (i != methParams.size() - 1) {
1603                                         print(", ");
1604                                 }
1605                         }
1606                         println(") { ");
1607                         if (isCallbackMethod)
1608                                 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
1609                         else
1610                                 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method);
1611                         println("}\n");
1612                         // Write the init callback helper method
1613                         if (isCallbackMethod) {
1614                                 writeInitCallbackCplusStub(callbackType, intDecl);
1615                                 writeInitCallbackSendInfoCplusStub(intDecl);
1616                         }
1617                 }
1618         }
1619
1620
1621         /**
1622          * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
1623          */
1624         private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
1625                         List<String> methPrmTypes, String method, String callbackType) {
1626
1627                 // Check if this is single object, array, or list of objects
1628                 boolean isArrayOrList = false;
1629                 String callbackParam = null;
1630                 for (int i = 0; i < methParams.size(); i++) {
1631
1632                         String paramType = methPrmTypes.get(i);
1633                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1634                                 String param = methParams.get(i);
1635                                 if (isArrayOrList(paramType, param)) {  // Generate loop
1636                                         println("for (" + paramType + "* cb : " + getSimpleIdentifier(param) + ") {");
1637                                         println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
1638                                         isArrayOrList = true;
1639                                         callbackParam = getSimpleIdentifier(param);
1640                                 } else
1641                                         println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(" +
1642                                                 getSimpleIdentifier(param) + ", objIdCnt++);");
1643                                 println("vecCallbackObj.push_back(skel);");
1644                                 if (isArrayOrList(paramType, param))
1645                                         println("}");
1646                         }
1647                 }
1648                 println("int numParam = " + methParams.size() + ";");
1649                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
1650                 String retType = intDecl.getMethodType(method);
1651                 String retTypeC = checkAndGetCplusType(retType);
1652                 println("string retType = \"" + checkAndGetCplusArrayType(retTypeC) + "\";");
1653                 // Generate array of parameter types
1654                 print("string paramCls[] = { ");
1655                 for (int i = 0; i < methParams.size(); i++) {
1656                         String paramType = methPrmTypes.get(i);
1657                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1658                                 print("\"int\"");
1659                         } else { // Generate normal classes if it's not a callback object
1660                                 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
1661                                 String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
1662                                 print("\"" + prmType + "\"");
1663                         }
1664                         if (i != methParams.size() - 1) // Check if this is the last element
1665                                 print(", ");
1666                 }
1667                 println(" };");
1668                 print("int ___paramCB = ");
1669                 if (isArrayOrList)
1670                         println(callbackParam + ".size();");
1671                 else
1672                         println("1;");
1673                 // Generate array of parameter objects
1674                 print("void* paramObj[] = { ");
1675                 for (int i = 0; i < methParams.size(); i++) {
1676                         String paramType = methPrmTypes.get(i);
1677                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1678                                 print("&___paramCB");
1679                         } else
1680                                 print(getSimpleIdentifier(methParams.get(i)));
1681                         if (i != methParams.size() - 1)
1682                                 print(", ");
1683                 }
1684                 println(" };");
1685                 // Check if this is "void"
1686                 if (retType.equals("void")) {
1687                         println("void* retObj = NULL;");
1688                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
1689                 } else { // We do have a return value
1690                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1691                                 println(checkAndGetCplusType(retType) + " retVal;");
1692                         else
1693                                 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
1694                         println("void* retObj = &retVal;");
1695                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
1696                         println("return retVal;");
1697                 }
1698         }
1699
1700
1701         /**
1702          * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
1703          */
1704         private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
1705                         List<String> methPrmTypes, String method) {
1706
1707                 println("int numParam = " + methParams.size() + ";");
1708                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
1709                 String retType = intDecl.getMethodType(method);
1710                 String retTypeC = checkAndGetCplusType(retType);
1711                 println("string retType = \"" + checkAndGetCplusArrayType(retTypeC) + "\";");
1712                 // Generate array of parameter types
1713                 print("string paramCls[] = { ");
1714                 for (int i = 0; i < methParams.size(); i++) {
1715                         String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
1716                         String paramType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
1717                         print("\"" + paramType + "\"");
1718                         // Check if this is the last element (don't print a comma)
1719                         if (i != methParams.size() - 1) {
1720                                 print(", ");
1721                         }
1722                 }
1723                 println(" };");
1724                 // Generate array of parameter objects
1725                 print("void* paramObj[] = { ");
1726                 for (int i = 0; i < methParams.size(); i++) {
1727                         print("&" + getSimpleIdentifier(methParams.get(i)));
1728                         // Check if this is the last element (don't print a comma)
1729                         if (i != methParams.size() - 1) {
1730                                 print(", ");
1731                         }
1732                 }
1733                 println(" };");
1734                 // Check if this is "void"
1735                 if (retType.equals("void")) {
1736                         println("void* retObj = NULL;");
1737                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
1738                 } else { // We do have a return value
1739                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1740                                 println(checkAndGetCplusType(retType) + " retVal;");
1741                         else
1742                                 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
1743                         println("void* retObj = &retVal;");
1744                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
1745                         println("return retVal;");
1746                 }
1747         }
1748
1749
1750         /**
1751          * HELPER: writePropertiesCplusStub() writes the properties of the stub class
1752          */
1753         private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
1754
1755                 println("IoTRMICall *rmiCall;");
1756                 //println("IoTRMIObject\t\t\t*rmiObj;");
1757                 println("string address;");
1758                 println("vector<int> ports;\n");
1759                 // Get the object Id
1760                 Integer objId = mapIntfaceObjId.get(intface);
1761                 println("const static int objectId = " + objId + ";");
1762                 mapNewIntfaceObjId.put(newIntface, objId);
1763                 mapIntfaceObjId.put(intface, objId++);
1764                 if (callbackExist) {
1765                 // We assume that each class only has one callback interface for now
1766                         Iterator it = callbackClasses.iterator();
1767                         String callbackType = (String) it.next();
1768                         println("// Callback properties");
1769                         println("IoTRMIObject *rmiObj;");
1770                         println("vector<" + callbackType + "*> vecCallbackObj;");
1771                         println("static int objIdCnt;");
1772                         // Generate permission stuff for callback stubs
1773                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(callbackType);
1774                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1775                                 String newCallbackIntface = intMeth.getKey();
1776                                 int newObjectId = mapNewIntfaceObjId.get(newCallbackIntface);
1777                                 println("const static int object" + newObjectId + "Id = " + newObjectId + ";");
1778                                 println("const static set<int> set" + newObjectId + "Allowed;");
1779                         }
1780                 }
1781                 println("\n");
1782         }
1783
1784
1785         /**
1786          * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
1787          */
1788         private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1789
1790                 println(newStubClass + 
1791                         "(int _port, const char* _address, int _rev, bool* _bResult, vector<int> _ports) {");
1792                 println("address = _address;");
1793                 println("ports = _ports;");
1794                 println("rmiCall = new IoTRMICall(_port, _address, _rev, _bResult);");
1795                 if (callbackExist) {
1796                         println("objIdCnt = 0;");
1797                         Iterator it = callbackClasses.iterator();
1798                         String callbackType = (String) it.next();
1799                         println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
1800                         println("th1.detach();");
1801                         println("___regCB();");
1802                 }
1803                 println("}\n");
1804         }
1805
1806
1807         /**
1808          * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
1809          */
1810         private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1811
1812                 println("~" + newStubClass + "() {");
1813                 println("if (rmiCall != NULL) {");
1814                 println("delete rmiCall;");
1815                 println("rmiCall = NULL;");
1816                 println("}");
1817                 if (callbackExist) {
1818                 // We assume that each class only has one callback interface for now
1819                         println("if (rmiObj != NULL) {");
1820                         println("delete rmiObj;");
1821                         println("rmiObj = NULL;");
1822                         println("}");
1823                         Iterator it = callbackClasses.iterator();
1824                         String callbackType = (String) it.next();
1825                         println("for(" + callbackType + "* cb : vecCallbackObj) {");
1826                         println("delete cb;");
1827                         println("cb = NULL;");
1828                         println("}");
1829                 }
1830                 println("}");
1831                 println("");
1832         }
1833
1834
1835         /**
1836          * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
1837          */
1838         private void writeCplusMethodCallbackPermission(String intface) {
1839
1840                 println("int methodId = IoTRMIObject::getMethodId(method);");
1841                 // Get all the different stubs
1842                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1843                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1844                         String newIntface = intMeth.getKey();
1845                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
1846                         println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
1847                         println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
1848                         println("exit(-1);");
1849                         println("}");
1850                 }
1851         }
1852
1853
1854         /**
1855          * HELPER: writeInitCallbackCplusStub() writes the initialization of callback
1856          */
1857         private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl) {
1858
1859                 println("void ___initCallBack() {");
1860                 println("bool bResult = false;");
1861                 println("rmiObj = new IoTRMIObject(ports[0], &bResult);");
1862                 println("while (true) {");
1863                 println("char* method = rmiObj->getMethodBytes();");
1864                 writeCplusMethodCallbackPermission(intface);
1865                 println("int objId = IoTRMIObject::getObjectId(method);");
1866                 println("if (objId < vecCallbackObj.size()) {   // Check if still within range");
1867                 println(intface + "_CallbackSkeleton* skel = dynamic_cast<" + intface + 
1868                         "_CallbackSkeleton*> (vecCallbackObj.at(objId));");
1869                 println("skel->invokeMethod(rmiObj);");
1870                 println("} else {");
1871                 println("cerr << \"Illegal object Id: \" << to_string(objId);");
1872                 // TODO: perhaps need to change this into "throw" to make it cleaner (allow stack unfolding)
1873                 println("exit(-1);");
1874                 println("}");
1875                 println("}");
1876                 println("}\n");
1877         }
1878
1879
1880         /**
1881          * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization of callback
1882          */
1883         private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) {
1884
1885                 // Generate info sending part
1886                 println("void ___regCB() {");
1887                 println("int numParam = 3;");
1888                 String method = "___initCallBack()";
1889                 println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";");
1890                 println("string retType = \"void\";");
1891                 println("string paramCls[] = { \"int\", \"string\", \"int\" };");
1892                 println("int rev = 0;");
1893                 println("void* paramObj[] = { &ports[0], &address, &rev };");
1894                 println("void* retObj = NULL;");
1895                 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
1896                 println("}\n");
1897         }
1898
1899
1900         /**
1901          * generateCPlusStubClasses() generate stubs based on the methods list in C++
1902          */
1903         public void generateCPlusStubClasses() throws IOException {
1904
1905                 // Create a new directory
1906                 String path = createDirectories(dir, subdir);
1907                 for (String intface : mapIntfacePTH.keySet()) {
1908
1909                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1910                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1911                                 // Open a new file to write into
1912                                 String newIntface = intMeth.getKey();
1913                                 String newStubClass = newIntface + "_Stub";
1914                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
1915                                 pw = new PrintWriter(new BufferedWriter(fw));
1916                                 // Write file headers
1917                                 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
1918                                 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
1919                                 println("#include <iostream>");
1920                                 // Find out if there are callback objects
1921                                 Set<String> methods = intMeth.getValue();
1922                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1923                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1924                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1925                                 boolean callbackExist = !callbackClasses.isEmpty();
1926                                 if (callbackExist)      // Need thread library if this has callback
1927                                         println("#include <thread>");
1928                                 println("#include \"" + newIntface + ".hpp\""); println("");            
1929                                 println("using namespace std;"); println("");
1930                                 println("class " + newStubClass + " : public " + newIntface); println("{");
1931                                 println("private:\n");
1932                                 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses);
1933                                 println("public:\n");
1934                                 // Add default constructor and destructor
1935                                 println(newStubClass + "() { }"); println("");
1936                                 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses);
1937                                 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
1938                                 // Write methods
1939                                 writeMethodCplusStub(methods, intDecl, callbackClasses);
1940                                 print("}"); println(";");
1941                                 if (callbackExist)
1942                                         writePermissionInitializationCplus(intface, newStubClass, intDecl);
1943                                 println("#endif");
1944                                 pw.close();
1945                                 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
1946                         }
1947                 }
1948         }
1949
1950
1951         /**
1952          * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class
1953          */
1954         private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
1955
1956                 println("IoTRMICall *rmiCall;");
1957                 // Get the object Id
1958                 println("static int objectId;");
1959                 if (callbackExist) {
1960                 // We assume that each class only has one callback interface for now
1961                         Iterator it = callbackClasses.iterator();
1962                         String callbackType = (String) it.next();
1963                         println("// Callback properties");
1964                         println("IoTRMIObject *rmiObj;");
1965                         println("vector<" + callbackType + "*> vecCallbackObj;");
1966                         println("static int objIdCnt;");
1967                         // TODO: Need to initialize address and ports if we want to have callback-in-callback
1968                         println("string address;");
1969                         println("vector<int> ports;\n");
1970                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(callbackType);
1971                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1972                                 String newCallbackIntface = intMeth.getKey();
1973                                 int newObjectId = mapNewIntfaceObjId.get(newCallbackIntface);
1974                                 println("const static int object" + newObjectId + "Id = " + newObjectId + ";");
1975                                 println("const static set<int> set" + newObjectId + "Allowed;");
1976                         }
1977                 }
1978                 println("\n");
1979         }
1980
1981
1982         /**
1983          * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class
1984          */
1985         private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1986
1987                 println(newStubClass + "(IoTRMICall* _rmiCall, int _objectId) {");
1988                 println("objectId = _objectId;");
1989                 println("rmiCall = _rmiCall;");
1990                 if (callbackExist) {
1991                         Iterator it = callbackClasses.iterator();
1992                         String callbackType = (String) it.next();
1993                         println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
1994                         println("th1.detach();");
1995                         println("___regCB();");
1996                 }
1997                 println("}\n");
1998         }
1999
2000
2001         /**
2002          * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++
2003          */
2004         public void generateCPlusCallbackStubClasses() throws IOException {
2005
2006                 // Create a new directory
2007                 String path = createDirectories(dir, subdir);
2008                 for (String intface : mapIntfacePTH.keySet()) {
2009
2010                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2011                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2012                                 // Open a new file to write into
2013                                 String newIntface = intMeth.getKey();
2014                                 String newStubClass = newIntface + "_CallbackStub";
2015                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
2016                                 pw = new PrintWriter(new BufferedWriter(fw));
2017                                 // Find out if there are callback objects
2018                                 Set<String> methods = intMeth.getValue();
2019                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2020                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2021                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2022                                 boolean callbackExist = !callbackClasses.isEmpty();
2023                                 // Write file headers
2024                                 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
2025                                 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
2026                                 println("#include <iostream>");
2027                                 if (callbackExist)
2028                                         println("#include <thread>");
2029                                 println("#include \"" + newIntface + ".hpp\""); println("");            
2030                                 println("using namespace std;"); println("");
2031                                 println("class " + newStubClass + " : public " + newIntface); println("{");
2032                                 println("private:\n");
2033                                 writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses);
2034                                 println("public:\n");
2035                                 // Add default constructor and destructor
2036                                 println(newStubClass + "() { }"); println("");
2037                                 writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses);
2038                                 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
2039                                 // Write methods
2040                                 writeMethodCplusStub(methods, intDecl, callbackClasses);
2041                                 println("};");
2042                                 if (callbackExist)
2043                                         writePermissionInitializationCplus(intface, newStubClass, intDecl);
2044                                 println("#endif");
2045                                 pw.close();
2046                                 System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp...");
2047                         }
2048                 }
2049         }
2050
2051
2052         /**
2053          * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
2054          */
2055         private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
2056
2057                 println(intface + " *mainObj;");
2058                 // Callback
2059                 if (callbackExist) {
2060                         Iterator it = callbackClasses.iterator();
2061                         String callbackType = (String) it.next();
2062                         String exchangeType = checkAndGetParamClass(callbackType);
2063                         println("// Callback properties");
2064                         println("static int objIdCnt;");
2065                         println("vector<" + exchangeType + "*> vecCallbackObj;");
2066                         println("IoTRMICall *rmiCall;");
2067                 }
2068                 println("IoTRMIObject *rmiObj;\n");
2069                 // Keep track of object Ids of all stubs registered to this interface
2070                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2071                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2072                         String newIntface = intMeth.getKey();
2073                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
2074                         println("const static int object" + newObjectId + "Id = " + newObjectId + ";");
2075                         println("const static set<int> set" + newObjectId + "Allowed;");
2076                 }
2077                 println("\n");
2078         }
2079
2080
2081         /**
2082          * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
2083          */
2084         private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
2085
2086                 // Keep track of object Ids of all stubs registered to this interface
2087                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2088                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2089                         String newIntface = intMeth.getKey();
2090                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
2091                         print("const set<int> " + newSkelClass + "::set" + newObjectId + "Allowed {");
2092                         Set<String> methodIds = intMeth.getValue();
2093                         int i = 0;
2094                         for (String methodId : methodIds) {
2095                                 int methodNumId = intDecl.getMethodNumId(methodId);
2096                                 print(Integer.toString(methodNumId));
2097                                 // Check if this is the last element (don't print a comma)
2098                                 if (i != methodIds.size() - 1) {
2099                                         print(", ");
2100                                 }
2101                                 i++;
2102                         }
2103                         println(" };");
2104                 }       
2105         }
2106
2107
2108         /**
2109          * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
2110          */
2111         private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist) {
2112
2113                 println(newSkelClass + "(" + intface + " *_mainObj, int _port) {");
2114                 println("bool _bResult = false;");
2115                 println("mainObj = _mainObj;");
2116                 println("rmiObj = new IoTRMIObject(_port, &_bResult);");
2117                 // Callback
2118                 if (callbackExist) {
2119                         println("objIdCnt = 0;");
2120                 }
2121                 //println("set0Allowed = Arrays.asList(object0Permission);");
2122                 println("___waitRequestInvokeMethod();");
2123                 println("}\n");
2124         }
2125
2126
2127         /**
2128          * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
2129          */
2130         private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
2131
2132                 println("~" + newSkelClass + "() {");
2133                 println("if (rmiObj != NULL) {");
2134                 println("delete rmiObj;");
2135                 println("rmiObj = NULL;");
2136                 println("}");
2137                 if (callbackExist) {
2138                 // We assume that each class only has one callback interface for now
2139                         println("if (rmiCall != NULL) {");
2140                         println("delete rmiCall;");
2141                         println("rmiCall = NULL;");
2142                         println("}");
2143                         Iterator it = callbackClasses.iterator();
2144                         String callbackType = (String) it.next();
2145                         String exchangeType = checkAndGetParamClass(callbackType);
2146                         println("for(" + exchangeType + "* cb : vecCallbackObj) {");
2147                         println("delete cb;");
2148                         println("cb = NULL;");
2149                         println("}");
2150                 }
2151                 println("}");
2152                 println("");
2153         }
2154
2155
2156         /**
2157          * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
2158          */
2159         private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
2160
2161                 if (methodType.equals("void"))
2162                         print("mainObj->" + methodId + "(");
2163                 else
2164                         print("return mainObj->" + methodId + "(");
2165                 for (int i = 0; i < methParams.size(); i++) {
2166
2167                         print(getSimpleIdentifier(methParams.get(i)));
2168                         // Check if this is the last element (don't print a comma)
2169                         if (i != methParams.size() - 1) {
2170                                 print(", ");
2171                         }
2172                 }
2173                 println(");");
2174         }
2175
2176
2177         /**
2178          * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class
2179          */
2180         private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton) {
2181
2182                 // This is a callback skeleton generation
2183                 if (callbackSkeleton)
2184                         println("void ___regCB(IoTRMIObject* rmiObj) {");
2185                 else
2186                         println("void ___regCB() {");
2187                 println("int numParam = 3;");
2188                 println("int param1 = 0;");
2189                 println("string param2 = \"\";");
2190                 println("int param3 = 0;");
2191                 println("void* paramObj[] = { &param1, &param2, &param3 };");
2192                 println("bool bResult = false;");
2193                 println("rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);");
2194                 println("}\n");
2195         }
2196
2197
2198         /**
2199          * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
2200          */
2201         private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
2202                         Set<String> callbackClasses, boolean callbackSkeleton) {
2203
2204                 for (String method : methods) {
2205
2206                         List<String> methParams = intDecl.getMethodParams(method);
2207                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2208                         String methodId = intDecl.getMethodId(method);
2209                         String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
2210                         print(methodType + " " + methodId + "(");
2211                         boolean isCallbackMethod = false;
2212                         String callbackType = null;
2213                         for (int i = 0; i < methParams.size(); i++) {
2214
2215                                 String origParamType = methPrmTypes.get(i);
2216                                 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
2217                                         isCallbackMethod = true;
2218                                         callbackType = origParamType;   
2219                                 }
2220                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2221                                 String methPrmType = checkAndGetCplusType(paramType);
2222                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2223                                 print(methParamComplete);
2224                                 // Check if this is the last element (don't print a comma)
2225                                 if (i != methParams.size() - 1) {
2226                                         print(", ");
2227                                 }
2228                         }
2229                         println(") {");
2230                         // Now, write the body of skeleton!
2231                         writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
2232                         println("}\n");
2233                         if (isCallbackMethod)
2234                                 writeInitCallbackCplusSkeleton(callbackSkeleton);
2235                 }
2236         }
2237
2238
2239         /**
2240          * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
2241          */
2242         private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
2243
2244                 for (int i = 0; i < methParams.size(); i++) {
2245                         String paramType = methPrmTypes.get(i);
2246                         String param = methParams.get(i);
2247                         //if (callbackType.equals(paramType)) {
2248                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2249                                 String exchParamType = checkAndGetParamClass(paramType);
2250                                 // Print array if this is array or list if this is a list of callback objects
2251                                 println("int numStubs" + i + " = 0;");
2252                         }
2253                 }
2254         }
2255
2256
2257         /**
2258          * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
2259          */
2260         private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
2261
2262                 // Iterate over callback objects
2263                 for (int i = 0; i < methParams.size(); i++) {
2264                         String paramType = methPrmTypes.get(i);
2265                         String param = methParams.get(i);
2266                         // Generate a loop if needed
2267                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2268                                 String exchParamType = checkAndGetParamClass(paramType);
2269                                 if (isArrayOrList(paramType, param)) {
2270                                         println("vector<" + exchParamType + "> stub;");
2271                                         println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
2272                                         println(exchParamType + "* cb" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
2273                                         println("stub" + i + ".push_back(cb);");
2274                                         println("vecCallbackObj.push_back(cb);");
2275                                         println("objIdCnt++;");
2276                                         println("}");
2277                                 } else {
2278                                         println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
2279                                         println("vecCallbackObj.push_back(stub" + i + ");");
2280                                         println("objIdCnt++;");
2281                                 }
2282                         }
2283                 }
2284         }
2285
2286
2287         /**
2288          * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
2289          */
2290         private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
2291                         List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
2292
2293                 // Generate array of parameter types
2294                 boolean isCallbackMethod = false;
2295                 String callbackType = null;
2296                 print("string paramCls[] = { ");
2297                 for (int i = 0; i < methParams.size(); i++) {
2298                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2299                         if (callbackClasses.contains(paramType)) {
2300                                 isCallbackMethod = true;
2301                                 callbackType = paramType;
2302                                 print("\"int\"");
2303                         } else {        // Generate normal classes if it's not a callback object
2304                                 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
2305                                 String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i));
2306                                 print("\"" + prmType + "\"");
2307                         }
2308                         if (i != methParams.size() - 1) {
2309                                 print(", ");
2310                         }
2311                 }
2312                 println(" };");
2313                 println("int numParam = " + methParams.size() + ";");
2314                 if (isCallbackMethod)
2315                         writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
2316                 // Generate parameters
2317                 for (int i = 0; i < methParams.size(); i++) {
2318                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2319                         if (!callbackClasses.contains(paramType)) {                     
2320                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2321                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2322                                 println(methParamComplete + ";");
2323                         }
2324                 }
2325                 // Generate array of parameter objects
2326                 print("void* paramObj[] = { ");
2327                 for (int i = 0; i < methParams.size(); i++) {
2328                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2329                         if (callbackClasses.contains(paramType))
2330                                 print("&numStubs" + i);
2331                         else
2332                                 print("&" + getSimpleIdentifier(methParams.get(i)));
2333                         if (i != methParams.size() - 1) {
2334                                 print(", ");
2335                         }
2336                 }
2337                 println(" };");
2338                 println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
2339                 if (isCallbackMethod)
2340                         writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
2341                 String retType = intDecl.getMethodType(method);
2342                 // Check if this is "void"
2343                 if (retType.equals("void")) {
2344                         print(methodId + "(");
2345                         for (int i = 0; i < methParams.size(); i++) {
2346                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2347                                 if (callbackClasses.contains(paramType))
2348                                         print("stub" + i);
2349                                 else
2350                                         print(getSimpleIdentifier(methParams.get(i)));
2351                                 if (i != methParams.size() - 1) {
2352                                         print(", ");
2353                                 }
2354                         }
2355                         println(");");
2356                 } else { // We do have a return value
2357                         print(checkAndGetCplusType(retType) + " retVal = " + methodId + "(");
2358                         for (int i = 0; i < methParams.size(); i++) {
2359                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2360                                 if (callbackClasses.contains(paramType))
2361                                         print("stub" + i);
2362                                 else
2363                                         print(getSimpleIdentifier(methParams.get(i)));
2364                                 if (i != methParams.size() - 1) {
2365                                         print(", ");
2366                                 }
2367                         }
2368                         println(");");
2369                         println("void* retObj = &retVal;");
2370                         String retTypeC = checkAndGetCplusType(retType);
2371                         println("rmiObj->sendReturnObj(retObj, \"" + checkAndGetCplusArrayType(retTypeC) + "\");");
2372                 }
2373         }
2374
2375
2376         /**
2377          * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
2378          */
2379         private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2380
2381                 // Use this set to handle two same methodIds
2382                 Set<String> uniqueMethodIds = new HashSet<String>();
2383                 for (String method : methods) {
2384
2385                         List<String> methParams = intDecl.getMethodParams(method);
2386                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2387                         String methodId = intDecl.getMethodId(method);
2388                         print("void ___");
2389                         String helperMethod = methodId;
2390                         if (uniqueMethodIds.contains(methodId))
2391                                 helperMethod = helperMethod + intDecl.getMethodNumId(method);
2392                         else
2393                                 uniqueMethodIds.add(methodId);
2394                         // Check if this is "void"
2395                         String retType = intDecl.getMethodType(method);
2396                         println(helperMethod + "() {");
2397                         // Now, write the helper body of skeleton!
2398                         writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
2399                         println("}\n");
2400                 }
2401         }
2402
2403
2404         /**
2405          * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
2406          */
2407         private void writeCplusMethodPermission(String intface) {
2408
2409                 // Get all the different stubs
2410                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2411                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2412                         String newIntface = intMeth.getKey();
2413                         int newObjectId = mapNewIntfaceObjId.get(newIntface);
2414                         println("if (_objectId == object" + newObjectId + "Id) {");
2415                         println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
2416                         println("cerr << \"Object with object Id: \" << _objectId << \"  is not allowed to access method: \" << methodId << endl;");
2417                         println("exit(-1);");
2418                         println("}");
2419                         println("else {");
2420                         println("cerr << \"Object Id: \" << _objectId << \" not recognized!\" << endl;");
2421                         println("exit(-1);");
2422                         println("}");
2423                         println("}");
2424                 }
2425         }
2426
2427
2428         /**
2429          * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
2430          */
2431         private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
2432
2433                 // Use this set to handle two same methodIds
2434                 Set<String> uniqueMethodIds = new HashSet<String>();
2435                 println("void ___waitRequestInvokeMethod() {");
2436                 // Write variables here if we have callbacks or enums or structs
2437                 println("while (true) {");
2438                 println("rmiObj->getMethodBytes();");
2439                 println("int _objectId = rmiObj->getObjectId();");
2440                 println("int methodId = rmiObj->getMethodId();");
2441                 // Generate permission check
2442                 writeCplusMethodPermission(intface);
2443                 println("switch (methodId) {");
2444                 // Print methods and method Ids
2445                 for (String method : methods) {
2446                         String methodId = intDecl.getMethodId(method);
2447                         int methodNumId = intDecl.getMethodNumId(method);
2448                         print("case " + methodNumId + ": ___");
2449                         String helperMethod = methodId;
2450                         if (uniqueMethodIds.contains(methodId))
2451                                 helperMethod = helperMethod + methodNumId;
2452                         else
2453                                 uniqueMethodIds.add(methodId);
2454                         println(helperMethod + "(); break;");
2455                 }
2456                 String method = "___initCallBack()";
2457                 // Print case -9999 (callback handler) if callback exists
2458                 if (callbackExist) {
2459                         int methodId = intDecl.getHelperMethodNumId(method);
2460                         println("case " + methodId + ": ___regCB(); break;");
2461                 }
2462                 println("default: ");
2463                 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
2464                 println("throw exception();");
2465                 println("}");
2466                 println("}");
2467                 println("}\n");
2468         }
2469
2470
2471         /**
2472          * generateCplusSkeletonClass() generate skeletons based on the methods list in C++
2473          */
2474         public void generateCplusSkeletonClass() throws IOException {
2475
2476                 // Create a new directory
2477                 String path = createDirectories(dir, subdir);
2478                 for (String intface : mapIntfacePTH.keySet()) {
2479                         // Open a new file to write into
2480                         String newSkelClass = intface + "_Skeleton";
2481                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
2482                         pw = new PrintWriter(new BufferedWriter(fw));
2483                         // Write file headers
2484                         println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
2485                         println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
2486                         println("#include <iostream>");
2487                         println("#include \"" + intface + ".hpp\"\n");
2488                         // Pass in set of methods and get import classes
2489                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2490                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2491                         List<String> methods = intDecl.getMethods();
2492                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, true);
2493                         List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
2494                         List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
2495                         printIncludeStatements(allIncludeClasses); println("");
2496                         println("using namespace std;\n");
2497                         // Find out if there are callback objects
2498                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2499                         boolean callbackExist = !callbackClasses.isEmpty();
2500                         // Write class header
2501                         println("class " + newSkelClass + " : public " + intface); println("{");
2502                         println("private:\n");
2503                         // Write properties
2504                         writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
2505                         println("public:\n");
2506                         // Write constructor
2507                         writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist);
2508                         // Write deconstructor
2509                         writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
2510                         // Write methods
2511                         writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false);
2512                         // Write method helper
2513                         writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses);
2514                         // Write waitRequestInvokeMethod() - main loop
2515                         writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
2516                         println("};");
2517                         writePermissionInitializationCplus(intface, newSkelClass, intDecl);
2518                         println("#endif");
2519                         pw.close();
2520                         System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
2521                 }
2522         }
2523
2524
2525         /**
2526          * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class
2527          */
2528         private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
2529
2530                 println(intface + " *mainObj;");
2531                 // Keep track of object Ids of all stubs registered to this interface
2532                 println("static int objectId;");
2533                 // Callback
2534                 if (callbackExist) {
2535                         Iterator it = callbackClasses.iterator();
2536                         String callbackType = (String) it.next();
2537                         String exchangeType = checkAndGetParamClass(callbackType);
2538                         println("// Callback properties");
2539                         println("IoTRMICall* rmiCall;");
2540                         println("vector<" + exchangeType + "*> vecCallbackObj;");
2541                         println("static int objIdCnt;");
2542                 }
2543                 println("\n");
2544         }
2545
2546
2547         /**
2548          * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class
2549          */
2550         private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist) {
2551
2552                 println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {");
2553                 println("mainObj = _mainObj;");
2554                 println("objectId = _objectId;");
2555                 // Callback
2556                 if (callbackExist) {
2557                         println("objIdCnt = 0;");
2558                 }
2559                 println("}\n");
2560         }
2561
2562
2563         /**
2564          * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
2565          */
2566         private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist, 
2567                         Set<String> callbackClasses) {
2568
2569                 println("~" + newStubClass + "() {");
2570                 if (callbackExist) {
2571                 // We assume that each class only has one callback interface for now
2572                         println("if (rmiCall != NULL) {");
2573                         println("delete rmiCall;");
2574                         println("rmiCall = NULL;");
2575                         println("}");
2576                         Iterator it = callbackClasses.iterator();
2577                         String callbackType = (String) it.next();
2578                         String exchangeType = checkAndGetParamClass(callbackType);
2579                         println("for(" + exchangeType + "* cb : vecCallbackObj) {");
2580                         println("delete cb;");
2581                         println("cb = NULL;");
2582                         println("}");
2583                 }
2584                 println("}");
2585                 println("");
2586         }
2587
2588
2589         /**
2590          * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of the callback skeleton class
2591          */
2592         private void writeMethodHelperCplusCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
2593                         Set<String> callbackClasses) {
2594
2595                 // Use this set to handle two same methodIds
2596                 Set<String> uniqueMethodIds = new HashSet<String>();
2597                 for (String method : methods) {
2598
2599                         List<String> methParams = intDecl.getMethodParams(method);
2600                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2601                         String methodId = intDecl.getMethodId(method);
2602                         print("void ___");
2603                         String helperMethod = methodId;
2604                         if (uniqueMethodIds.contains(methodId))
2605                                 helperMethod = helperMethod + intDecl.getMethodNumId(method);
2606                         else
2607                                 uniqueMethodIds.add(methodId);
2608                         // Check if this is "void"
2609                         String retType = intDecl.getMethodType(method);
2610                         println(helperMethod + "(IoTRMIObject* rmiObj) {");
2611                         // Now, write the helper body of skeleton!
2612                         writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
2613                         println("}\n");
2614                 }
2615         }
2616
2617
2618         /**
2619          * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class
2620          */
2621         private void writeCplusCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, 
2622                         boolean callbackExist) {
2623
2624                 // Use this set to handle two same methodIds
2625                 Set<String> uniqueMethodIds = new HashSet<String>();
2626                 println("void invokeMethod(IoTRMIObject* rmiObj) {");
2627                 // Write variables here if we have callbacks or enums or structs
2628                 println("int methodId = rmiObj->getMethodId();");
2629                 // TODO: code the permission check here!
2630                 println("switch (methodId) {");
2631                 // Print methods and method Ids
2632                 for (String method : methods) {
2633                         String methodId = intDecl.getMethodId(method);
2634                         int methodNumId = intDecl.getMethodNumId(method);
2635                         print("case " + methodNumId + ": ___");
2636                         String helperMethod = methodId;
2637                         if (uniqueMethodIds.contains(methodId))
2638                                 helperMethod = helperMethod + methodNumId;
2639                         else
2640                                 uniqueMethodIds.add(methodId);
2641                         println(helperMethod + "(rmiObj); break;");
2642                 }
2643                 String method = "___initCallBack()";
2644                 // Print case -9999 (callback handler) if callback exists
2645                 if (callbackExist) {
2646                         int methodId = intDecl.getHelperMethodNumId(method);
2647                         println("case " + methodId + ": ___regCB(rmiObj); break;");
2648                 }
2649                 println("default: ");
2650                 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
2651                 println("throw exception();");
2652                 println("}");
2653                 println("}\n");
2654         }
2655
2656
2657
2658         /**
2659          * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++
2660          */
2661         public void generateCplusCallbackSkeletonClass() throws IOException {
2662
2663                 // Create a new directory
2664                 String path = createDirectories(dir, subdir);
2665                 for (String intface : mapIntfacePTH.keySet()) {
2666                         // Open a new file to write into
2667                         String newSkelClass = intface + "_CallbackSkeleton";
2668                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
2669                         pw = new PrintWriter(new BufferedWriter(fw));
2670                         // Write file headers
2671                         println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
2672                         println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
2673                         println("#include <iostream>");
2674                         println("#include \"" + intface + ".hpp\"\n");
2675                         // Pass in set of methods and get import classes
2676                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2677                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2678                         List<String> methods = intDecl.getMethods();
2679                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, true);
2680                         List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
2681                         List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
2682                         printIncludeStatements(allIncludeClasses); println("");                 
2683                         // Find out if there are callback objects
2684                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2685                         boolean callbackExist = !callbackClasses.isEmpty();
2686                         println("using namespace std;\n");
2687                         // Write class header
2688                         println("class " + newSkelClass + " : public " + intface); println("{");
2689                         println("private:\n");
2690                         // Write properties
2691                         writePropertiesCplusCallbackSkeleton(intface, callbackExist, callbackClasses);
2692                         println("public:\n");
2693                         // Write constructor
2694                         writeConstructorCplusCallbackSkeleton(newSkelClass, intface, callbackExist);
2695                         // Write deconstructor
2696                         writeDeconstructorCplusCallbackSkeleton(newSkelClass, callbackExist, callbackClasses);
2697                         // Write methods
2698                         writeMethodCplusSkeleton(methods, intDecl, callbackClasses, true);
2699                         // Write method helper
2700                         writeMethodHelperCplusCallbackSkeleton(methods, intDecl, callbackClasses);
2701                         // Write waitRequestInvokeMethod() - main loop
2702                         writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
2703                         println("};");
2704                         println("#endif");
2705                         pw.close();
2706                         System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp...");
2707                 }
2708         }
2709
2710
2711         /**
2712          * generateInitializer() generate initializer based on type
2713          */
2714         public String generateCplusInitializer(String type) {
2715
2716                 // Generate dummy returns for now
2717                 if (type.equals("short")||
2718                         type.equals("int")      ||
2719                         type.equals("long") ||
2720                         type.equals("float")||
2721                         type.equals("double")) {
2722
2723                         return "0";
2724                 } else if ( type.equals("String") ||
2725                                         type.equals("string")) {
2726   
2727                         return "\"\"";
2728                 } else if ( type.equals("char") ||
2729                                         type.equals("byte")) {
2730
2731                         return "\' \'";
2732                 } else if ( type.equals("boolean")) {
2733
2734                         return "false";
2735                 } else {
2736                         return "NULL";
2737                 }
2738         }
2739
2740
2741         /**
2742          * generateReturnStmt() generate return statement based on methType
2743          */
2744         public String generateReturnStmt(String methType) {
2745
2746                 // Generate dummy returns for now
2747                 if (methType.equals("short")||
2748                         methType.equals("int")  ||
2749                         methType.equals("long") ||
2750                         methType.equals("float")||
2751                         methType.equals("double")) {
2752
2753                         return "1";
2754                 } else if ( methType.equals("String")) {
2755   
2756                         return "\"a\"";
2757                 } else if ( methType.equals("char") ||
2758                                         methType.equals("byte")) {
2759
2760                         return "\'a\'";
2761                 } else if ( methType.equals("boolean")) {
2762
2763                         return "true";
2764                 } else {
2765                         return "null";
2766                 }
2767         }
2768
2769
2770         /**
2771          * setDirectory() sets a new directory for stub files
2772          */
2773         public void setDirectory(String _subdir) {
2774
2775                 subdir = _subdir;
2776         }
2777
2778
2779         /**
2780          * printUsage() prints the usage of this compiler
2781          */
2782         public static void printUsage() {
2783
2784                 System.out.println();
2785                 System.out.println("Sentinel interface and stub compiler version 1.0");
2786                 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
2787                 System.out.println("All rights reserved.");
2788                 System.out.println("Usage:");
2789                 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
2790                 System.out.println("\t\tDisplay this help texts\n\n");
2791                 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
2792                 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
2793                 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
2794                 System.out.println("Options:");
2795                 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
2796                 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
2797                 System.out.println();
2798         }
2799
2800
2801         /**
2802          * parseFile() prepares Lexer and Parser objects, then parses the file
2803          */
2804         public static ParseNode parseFile(String file) {
2805
2806                 ParseNode pn = null;
2807                 try {
2808                         ComplexSymbolFactory csf = new ComplexSymbolFactory();
2809                         ScannerBuffer lexer = 
2810                                 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
2811                         Parser parse = new Parser(lexer,csf);
2812                         pn = (ParseNode) parse.parse().value;
2813                 } catch (Exception e) {
2814                         e.printStackTrace();
2815                         throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
2816                 }
2817
2818                 return pn;
2819         }
2820
2821
2822         /**================
2823          * Helper functions
2824          **================
2825          */
2826         boolean newline=true;
2827         int tablevel=0;
2828
2829         private void print(String str) {
2830                 if (newline) {
2831                         int tab=tablevel;
2832                         if (str.equals("}"))
2833                                 tab--;
2834                         for(int i=0; i<tab; i++)
2835                                 pw.print("\t");
2836                 }
2837                 pw.print(str);
2838                 updatetabbing(str);
2839                 newline=false;
2840         }
2841
2842
2843         /**
2844          * This function converts Java to C++ type for compilation
2845          */
2846         private String convertType(String jType) {
2847
2848                 return mapPrimitives.get(jType);
2849         }
2850
2851
2852         private void println(String str) {
2853                 if (newline) {
2854                         int tab = tablevel;
2855                         if (str.contains("}") && !str.contains("{"))
2856                                 tab--;
2857                         for(int i=0; i<tab; i++)
2858                                 pw.print("\t");
2859                 }
2860                 pw.println(str);
2861                 updatetabbing(str);
2862                 newline = true;
2863         }
2864
2865
2866         private void updatetabbing(String str) {
2867
2868                 tablevel+=count(str,'{')-count(str,'}');
2869         }
2870
2871
2872         private int count(String str, char key) {
2873                 char[] array = str.toCharArray();
2874                 int count = 0;
2875                 for(int i=0; i<array.length; i++) {
2876                         if (array[i] == key)
2877                                 count++;
2878                 }
2879                 return count;
2880         }
2881
2882
2883         private void createDirectory(String dirName) {
2884
2885                 File file = new File(dirName);
2886                 if (!file.exists()) {
2887                         if (file.mkdir()) {
2888                                 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
2889                         } else {
2890                                 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
2891                         }
2892                 } else {
2893                         System.out.println("IoTCompiler: Directory " + dirName + " exists...");
2894                 }
2895         }
2896
2897
2898         // Create a directory and possibly a sub directory
2899         private String createDirectories(String dir, String subdir) {
2900
2901                 String path = dir;
2902                 createDirectory(path);
2903                 if (subdir != null) {
2904                         path = path + "/" + subdir;
2905                         createDirectory(path);
2906                 }
2907                 return path;
2908         }
2909
2910
2911         // Inserting array members into a Map object
2912         // that maps arrKey to arrVal objects
2913         private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
2914
2915                 for(int i = 0; i < arrKey.length; i++) {
2916
2917                         map.put(arrKey[i], arrVal[i]);
2918                 }
2919         }
2920
2921
2922         // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
2923         private ParamCategory getParamCategory(String paramType) {
2924
2925                 if (mapPrimitives.containsKey(paramType)) {
2926                         return ParamCategory.PRIMITIVES;
2927                 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
2928                 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
2929                         return ParamCategory.NONPRIMITIVES;
2930                 } else
2931                         return ParamCategory.USERDEFINED;
2932         }
2933
2934
2935         // Return full class name for non-primitives to generate Java import statements
2936         // e.g. java.util.Set for Set, java.util.Map for Map
2937         private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
2938
2939                 return mapNonPrimitivesJava.get(paramNonPrimitives);
2940         }
2941
2942
2943         // Return full class name for non-primitives to generate Cplus include statements
2944         // e.g. #include <set> for Set, #include <map> for Map
2945         private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
2946
2947                 return mapNonPrimitivesCplus.get(paramNonPrimitives);
2948         }
2949
2950
2951         // Get simple types, e.g. HashSet for HashSet<...>
2952         // Basically strip off the "<...>"
2953         private String getSimpleType(String paramType) {
2954
2955                 // Check if this is generics
2956                 if(paramType.contains("<")) {
2957                         String[] type = paramType.split("<");
2958                         return type[0];
2959                 } else
2960                         return paramType;
2961         }
2962
2963
2964         // Generate a set of standard classes for import statements
2965         private List<String> getStandardJavaImportClasses() {
2966
2967                 List<String> importClasses = new ArrayList<String>();
2968                 // Add the standard list first
2969                 importClasses.add("java.io.IOException");
2970                 importClasses.add("java.util.List");
2971                 importClasses.add("java.util.ArrayList");
2972                 importClasses.add("java.util.Arrays");
2973                 importClasses.add("iotrmi.Java.IoTRMICall");
2974                 importClasses.add("iotrmi.Java.IoTRMIObject");
2975
2976                 return importClasses;
2977         }
2978
2979
2980         // Generate a set of standard classes for import statements
2981         private List<String> getStandardCplusIncludeClasses() {
2982
2983                 List<String> importClasses = new ArrayList<String>();
2984                 // Add the standard list first
2985                 importClasses.add("<vector>");
2986                 importClasses.add("<set>");
2987                 importClasses.add("\"IoTRMICall.hpp\"");
2988                 importClasses.add("\"IoTRMIObject.hpp\"");
2989
2990                 return importClasses;
2991         }
2992
2993
2994         // Generate a set of standard classes for import statements
2995         private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
2996
2997                 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
2998                 // Iterate over the list of import classes
2999                 for (String str : libClasses) {
3000                         if (!allLibClasses.contains(str)) {
3001                                 allLibClasses.add(str);
3002                         }
3003                 }
3004
3005                 return allLibClasses;
3006         }
3007
3008
3009
3010         // Generate a set of classes for import statements
3011         private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
3012
3013                 Set<String> importClasses = new HashSet<String>();
3014                 for (String method : methods) {
3015                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3016                         for (String paramType : methPrmTypes) {
3017
3018                                 String simpleType = getSimpleType(paramType);
3019                                 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
3020                                         importClasses.add(getNonPrimitiveJavaClass(simpleType));
3021                                 }
3022                         }
3023                 }
3024                 return importClasses;
3025         }
3026
3027
3028         // Generate a set of classes for include statements
3029         private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, boolean needExchange) {
3030
3031                 Set<String> includeClasses = new HashSet<String>();
3032                 for (String method : methods) {
3033
3034                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3035                         List<String> methParams = intDecl.getMethodParams(method);
3036                         for (int i = 0; i < methPrmTypes.size(); i++) {
3037
3038                                 String simpleType = getSimpleType(methPrmTypes.get(i));
3039                                 String param = methParams.get(i);
3040                                 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
3041                                         includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
3042                                 } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
3043                                         // For original interface, we need it exchanged... not for stub interfaces
3044                                         if (needExchange) {
3045                                                 includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
3046                                                 includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\"");
3047                                         } else {
3048                                                 includeClasses.add("\"" + simpleType + ".hpp\"");
3049                                                 includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\"");
3050                                         }
3051                                 } else if (param.contains("[]")) {
3052                                 // Check if this is array for C++; translate into vector
3053                                         includeClasses.add("<vector>");
3054                                 }
3055                         }
3056                 }
3057                 return includeClasses;
3058         }
3059
3060
3061         // Generate a set of callback classes
3062         private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
3063
3064                 Set<String> callbackClasses = new HashSet<String>();
3065                 for (String method : methods) {
3066
3067                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3068                         List<String> methParams = intDecl.getMethodParams(method);
3069                         for (int i = 0; i < methPrmTypes.size(); i++) {
3070
3071                                 String type = methPrmTypes.get(i);
3072                                 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
3073                                         callbackClasses.add(type);
3074                                 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
3075                                 // Can be a List<...> of callback objects ...
3076                                         String genericType = getTypeOfGeneric(type)[0];
3077                                         if (getParamCategory(type) == ParamCategory.USERDEFINED) {
3078                                                 callbackClasses.add(type);
3079                                         }
3080                                 }
3081                         }
3082                 }
3083                 return callbackClasses;
3084         }
3085
3086
3087         private void printImportStatements(Collection<String> importClasses) {
3088
3089                 for(String cls : importClasses) {
3090                         println("import " + cls + ";");
3091                 }
3092         }
3093
3094
3095         private void printIncludeStatements(Collection<String> includeClasses) {
3096
3097                 for(String cls : includeClasses) {
3098                         println("#include " + cls);
3099                 }
3100         }
3101
3102
3103         // Get the C++ version of a non-primitive type
3104         // e.g. set for Set and map for Map
3105         // Input nonPrimitiveType has to be generics in format
3106         private String[] getTypeOfGeneric(String nonPrimitiveType) {
3107
3108                 // Handle <, >, and , for 2-type generic/template
3109                 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
3110                 return substr;
3111         }
3112
3113
3114         // This helper function strips off array declaration, e.g. D[] becomes D
3115         private String getSimpleIdentifier(String ident) {
3116
3117                 // Handle [ for array declaration
3118                 String substr = ident;
3119                 if (ident.contains("[]")) {
3120                         substr = ident.split("\\[\\]")[0];
3121                 }
3122                 return substr;
3123         }
3124
3125
3126         private String checkAndGetCplusType(String paramType) {
3127
3128                 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
3129                         return convertType(paramType);
3130                 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
3131
3132                         // Check for generic/template format
3133                         if (paramType.contains("<") && paramType.contains(">")) {
3134
3135                                 String genericClass = getSimpleType(paramType);
3136                                 String[] genericType = getTypeOfGeneric(paramType);
3137                                 String cplusTemplate = null;
3138                                 if (genericType.length == 1) // Generic/template with one type
3139                                         cplusTemplate = getNonPrimitiveCplusClass(genericClass) + 
3140                                                 "<" + convertType(genericType[0]) + ">";
3141                                 else // Generic/template with two types
3142                                         cplusTemplate = getNonPrimitiveCplusClass(genericClass) + 
3143                                                 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
3144                                 return cplusTemplate;
3145                         } else
3146                                 return getNonPrimitiveCplusClass(paramType);
3147                 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
3148                         return paramType + "*";
3149                 } else
3150                         // Just return it as is if it's not non-primitives
3151                         return paramType;
3152                         //return checkAndGetParamClass(paramType, true);
3153         }
3154
3155
3156         // Detect array declaration, e.g. int A[],
3157         //              then generate "int A[]" in C++ as "vector<int> A"
3158         private String checkAndGetCplusArray(String paramType, String param) {
3159
3160                 String paramComplete = null;
3161                 // Check for array declaration
3162                 if (param.contains("[]")) {
3163                         paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
3164                 } else
3165                         // Just return it as is if it's not an array
3166                         paramComplete = paramType + " " + param;
3167
3168                 return paramComplete;
3169         }
3170         
3171
3172         // Detect array declaration, e.g. int A[],
3173         //              then generate "int A[]" in C++ as "vector<int> A"
3174         // This method just returns the type
3175         private String checkAndGetCplusArrayType(String paramType) {
3176
3177                 String paramTypeRet = null;
3178                 // Check for array declaration
3179                 if (paramType.contains("[]")) {
3180                         String type = paramType.split("\\[\\]")[0];
3181                         paramTypeRet = checkAndGetCplusType(type) + "[]";
3182                 } else if (paramType.contains("vector")) {
3183                         // Just return it as is if it's not an array
3184                         String type = paramType.split("<")[1].split(">")[0];
3185                         paramTypeRet = checkAndGetCplusType(type) + "[]";
3186                 } else
3187                         paramTypeRet = paramType;
3188
3189                 return paramTypeRet;
3190         }
3191         
3192         
3193         // Detect array declaration, e.g. int A[],
3194         //              then generate "int A[]" in C++ as "vector<int> A"
3195         // This method just returns the type
3196         private String checkAndGetCplusArrayType(String paramType, String param) {
3197
3198                 String paramTypeRet = null;
3199                 // Check for array declaration
3200                 if (param.contains("[]")) {
3201                         paramTypeRet = checkAndGetCplusType(paramType) + "[]";
3202                 } else if (paramType.contains("vector")) {
3203                         // Just return it as is if it's not an array
3204                         String type = paramType.split("<")[1].split(">")[0];
3205                         paramTypeRet = checkAndGetCplusType(type) + "[]";
3206                 } else
3207                         paramTypeRet = paramType;
3208
3209                 return paramTypeRet;
3210         }
3211
3212
3213         // Detect array declaration, e.g. int A[],
3214         //              then generate type "int[]"
3215         private String checkAndGetArray(String paramType, String param) {
3216
3217                 String paramTypeRet = null;
3218                 // Check for array declaration
3219                 if (param.contains("[]")) {
3220                         paramTypeRet = paramType + "[]";
3221                 } else
3222                         // Just return it as is if it's not an array
3223                         paramTypeRet = paramType;
3224
3225                 return paramTypeRet;
3226         }
3227
3228
3229         // Is array or list?
3230         private boolean isArrayOrList(String paramType, String param) {
3231
3232                 // Check for array declaration
3233                 if (isArray(paramType, param))
3234                         return true;
3235                 else if (isList(paramType, param))
3236                         return true;
3237                 else
3238                         return false;
3239         }
3240
3241
3242         // Is array or list?
3243         private boolean isArray(String paramType, String param) {
3244
3245                 // Check for array declaration
3246                 if (param.contains("[]"))
3247                         return true;
3248                 else
3249                         return false;
3250         }
3251
3252
3253         // Is array or list?
3254         private boolean isList(String paramType, String param) {
3255
3256                 // Check for array declaration
3257                 if (paramType.contains("List"))
3258                         return true;
3259                 else
3260                         return false;
3261         }
3262
3263
3264         // Get the right type for a callback object
3265         private String checkAndGetParamClass(String paramType) {
3266
3267                 // Check if this is generics
3268                 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
3269                         return exchangeParamType(paramType);
3270                 } else
3271                         return paramType;
3272         }
3273
3274
3275         // Returns the other interface for type-checking purposes for USERDEFINED
3276         //              classes based on the information provided in multiple policy files
3277         // e.g. return CameraWithXXX instead of Camera
3278         private String exchangeParamType(String intface) {
3279
3280                 // Param type that's passed is the interface name we need to look for
3281                 //              in the map of interfaces, based on available policy files.
3282                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3283                 if (decHandler != null) {
3284                 // We've found the required interface policy files
3285                         RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
3286                         Set<String> setExchInt = reqDecl.getInterfaces();
3287                         if (setExchInt.size() == 1) {
3288                                 Iterator iter = setExchInt.iterator();
3289                                 return (String) iter.next();
3290                         } else {
3291                                 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() + 
3292                                         ". Only one new interface can be declared if the object " + intface +
3293                                         " needs to be passed in as an input parameter!");
3294                         }
3295                 } else {
3296                 // NULL value - this means policy files missing
3297                         throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
3298                                 "... Please provide the necessary policy files for user-defined types." +
3299                                 " If this is an array please type the brackets after the variable name," +
3300                                 " e.g. \"String str[]\", not \"String[] str\"." +
3301                                 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
3302                                 " supports List/ArrayList (Java) or list (C++).");
3303                 }
3304         }
3305
3306
3307         public static void main(String[] args) throws Exception {
3308
3309                 // If there is no argument or just "--help" or "-h", then invoke printUsage()
3310                 if ((args[0].equals("-help") ||
3311                          args[0].equals("--help")||
3312                          args[0].equals("-h"))   ||
3313                         (args.length == 0)) {
3314
3315                         IoTCompiler.printUsage();
3316
3317                 } else if (args.length > 1) {
3318
3319                         IoTCompiler comp = new IoTCompiler();
3320                         int i = 0;                              
3321                         do {
3322                                 // Parse main policy file
3323                                 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
3324                                 // Parse "requires" policy file
3325                                 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
3326                                 // Get interface name
3327                                 String intface = ParseTreeHandler.getOrigIntface(pnPol);
3328                                 comp.setDataStructures(intface, pnPol, pnReq);
3329                                 comp.getMethodsForIntface(intface);
3330                                 i = i + 2;
3331                         // 1) Check if this is the last option before "-java" or "-cplus"
3332                         // 2) Check if this is really the last option (no "-java" or "-cplus")
3333                         } while(!args[i].equals("-java") &&
3334                                         !args[i].equals("-cplus") &&
3335                                         (i < args.length));
3336
3337                         // Generate everything if we don't see "-java" or "-cplus"
3338                         if (i == args.length) {
3339                                 comp.generateJavaLocalInterfaces();
3340                                 comp.generateJavaInterfaces();
3341                                 comp.generateJavaStubClasses();
3342                                 comp.generateJavaCallbackStubClasses();
3343                                 comp.generateJavaSkeletonClass();
3344                                 comp.generateJavaCallbackSkeletonClass();
3345                                 comp.generateCplusLocalInterfaces();
3346                                 comp.generateCPlusInterfaces();
3347                                 comp.generateCPlusStubClasses();
3348                                 comp.generateCPlusCallbackStubClasses();
3349                                 comp.generateCplusSkeletonClass();
3350                                 comp.generateCplusCallbackSkeletonClass();
3351                         } else {
3352                         // Check other options
3353                                 while(i < args.length) {
3354                                         // Error checking
3355                                         if (!args[i].equals("-java") &&
3356                                                 !args[i].equals("-cplus")) {
3357                                                 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
3358                                         } else {
3359                                                 if (i + 1 < args.length) {
3360                                                         comp.setDirectory(args[i+1]);
3361                                                 } else
3362                                                         throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
3363
3364                                                 if (args[i].equals("-java")) {
3365                                                         comp.generateJavaLocalInterfaces();
3366                                                         comp.generateJavaInterfaces();
3367                                                         comp.generateJavaStubClasses();
3368                                                         comp.generateJavaCallbackStubClasses();
3369                                                         comp.generateJavaSkeletonClass();
3370                                                         comp.generateJavaCallbackSkeletonClass();
3371                                                 } else {
3372                                                         comp.generateCplusLocalInterfaces();
3373                                                         comp.generateCPlusInterfaces();
3374                                                         comp.generateCPlusStubClasses();
3375                                                         comp.generateCPlusCallbackStubClasses();
3376                                                         comp.generateCplusSkeletonClass();
3377                                                         comp.generateCplusCallbackSkeletonClass();
3378                                                 }
3379                                         }
3380                                         i = i + 2;
3381                                 }
3382                         }
3383                 } else {
3384                 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
3385                         IoTCompiler.printUsage();
3386                         throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");
3387                 }
3388         }
3389 }
3390
3391
3392
3393