3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
6 import java.util.Arrays;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.List;
17 import iotpolicy.parser.Lexer;
18 import iotpolicy.parser.Parser;
19 import iotpolicy.tree.ParseNode;
20 import iotpolicy.tree.ParseNodeVector;
21 import iotpolicy.tree.ParseTreeHandler;
22 import iotpolicy.tree.Declaration;
23 import iotpolicy.tree.DeclarationHandler;
24 import iotpolicy.tree.CapabilityDecl;
25 import iotpolicy.tree.InterfaceDecl;
26 import iotpolicy.tree.RequiresDecl;
27 import iotpolicy.tree.EnumDecl;
28 import iotpolicy.tree.StructDecl;
30 import iotrmi.Java.IoTRMITypes;
33 /** Class IoTCompiler is the main interface/stub compiler for
34 * files generation. This class calls helper classes
35 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
36 * RequiresDecl, ParseTreeHandler, etc.
38 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
42 public class IoTCompiler {
47 // Maps multiple interfaces to multiple objects of ParseTreeHandler
48 private Map<String,ParseTreeHandler> mapIntfacePTH;
49 private Map<String,DeclarationHandler> mapIntDeclHand;
50 private Map<String,Map<String,Set<String>>> mapInt2NewInts;
51 // Data structure to store our types (primitives and non-primitives) for compilation
52 private Map<String,String> mapPrimitives;
53 private Map<String,String> mapNonPrimitivesJava;
54 private Map<String,String> mapNonPrimitivesCplus;
55 // Other data structures
56 private Map<String,Integer> mapIntfaceObjId; // Maps interface name to object Id
57 private Map<String,Integer> mapNewIntfaceObjId; // Maps new interface name to its object Id (keep track of stubs)
58 private PrintWriter pw;
60 private String subdir;
65 private final static String OUTPUT_DIRECTORY = "output_files";
67 private enum ParamCategory {
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
77 public IoTCompiler() {
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);
91 dir = OUTPUT_DIRECTORY;
97 * setDataStructures() sets parse tree and other data structures based on policy files.
99 * It also generates parse tree (ParseTreeHandler) and
100 * copies useful information from parse tree into
101 * InterfaceDecl, CapabilityDecl, and RequiresDecl
103 * Additionally, the data structure handles are
104 * returned from tree-parsing for further process.
107 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
109 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
110 DeclarationHandler decHandler = new DeclarationHandler();
111 // Process ParseNode and generate Declaration objects
113 ptHandler.processInterfaceDecl();
114 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
115 decHandler.addInterfaceDecl(origInt, intDecl);
117 ptHandler.processCapabilityDecl();
118 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
119 decHandler.addCapabilityDecl(origInt, capDecl);
121 ptHandler.processRequiresDecl();
122 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
123 decHandler.addRequiresDecl(origInt, reqDecl);
125 ptHandler.processEnumDecl();
126 EnumDecl enumDecl = ptHandler.getEnumDecl();
127 decHandler.addEnumDecl(origInt, enumDecl);
129 ptHandler.processStructDecl();
130 StructDecl structDecl = ptHandler.getStructDecl();
131 decHandler.addStructDecl(origInt, structDecl);
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));
141 * getMethodsForIntface() reads for methods in the data structure
143 * It is going to give list of methods for a certain interface
144 * based on the declaration of capabilities.
146 public void getMethodsForIntface(String origInt) {
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) {
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) {
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) {
169 // Add methods into setMethods
170 // This is to also handle redundancies (say two capabilities
171 // share the same methods)
172 setMethods.add(strMeth);
175 // Add interface and methods information into map
176 mapNewIntMethods.put(strInt, setMethods);
178 // Map the map of interface-methods to the original interface
179 mapInt2NewInts.put(origInt, mapNewIntMethods);
184 * HELPER: writeMethodJavaLocalInterface() writes the method of the interface
186 private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
188 for (String method : methods) {
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) {
210 * HELPER: writeMethodJavaInterface() writes the method of the interface
212 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
214 for (String method : methods) {
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) {
236 * HELPER: writeEnumJava() writes the enumeration declaration
238 private void writeEnumJava(EnumDecl enumDecl) {
240 Set<String> enumTypes = enumDecl.getEnumDeclarations();
241 // Iterate over enum declarations
242 for (String enType : enumTypes) {
244 println("public enum " + enType + " {");
245 List<String> enumMembers = enumDecl.getMembers(enType);
246 for (int i = 0; i < enumMembers.size(); i++) {
248 String member = enumMembers.get(i);
250 // Check if this is the last element (don't print a comma)
251 if (i != enumMembers.size() - 1)
262 * HELPER: writeStructJava() writes the struct declaration
264 private void writeStructJava(StructDecl structDecl) {
266 List<String> structTypes = structDecl.getStructTypes();
267 // Iterate over enum declarations
268 for (String stType : structTypes) {
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++) {
275 String memberType = structMemberTypes.get(i);
276 String member = structMembers.get(i);
277 println("public static " + memberType + " " + member + ";");
285 * generateJavaLocalInterface() writes the local interface and provides type-checking.
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.
292 public void generateJavaLocalInterfaces() throws IOException {
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
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);
316 writeMethodJavaLocalInterface(methods, intDecl);
319 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
325 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
327 public void generateJavaInterfaces() throws IOException {
329 // Create a new directory
330 String path = createDirectories(dir, subdir);
331 for (String intface : mapIntfacePTH.keySet()) {
333 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
334 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
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
347 println("public interface " + newIntface + " {\n");
349 writeMethodJavaInterface(intMeth.getValue(), intDecl);
352 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
359 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
361 private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
363 println("private IoTRMICall rmiCall;");
364 println("private String address;");
365 println("private int[] ports;\n");
367 Integer objId = mapIntfaceObjId.get(intface);
368 println("private final static int objectId = " + objId + ";");
369 mapNewIntfaceObjId.put(newIntface, objId);
370 mapIntfaceObjId.put(intface, objId++);
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 = { ");
391 for (String methodId : methodIds) {
392 int methodNumId = intDecl.getMethodNumId(methodId);
393 print(Integer.toString(methodNumId));
394 // Check if this is the last element (don't print a comma)
395 if (i != methodIds.size() - 1) {
401 println("private List<Integer> set" + newObjectId + "Allowed;");
409 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
411 private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
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);");
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);");
426 println("listCallbackObj = new ArrayList<" + callbackType + ">();");
427 println("___initCallBack();");
434 * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
436 private void writeJavaMethodCallbackPermission(String intface) {
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);");
452 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
454 private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl) {
456 println("public void ___initCallBack() {");
457 // Generate main thread for callbacks
458 println("Thread thread = new Thread() {");
459 println("public void run() {");
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);");
470 println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");");
473 println("} catch (Exception ex) {");
474 println("ex.printStackTrace();");
475 println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");");
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);");
492 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
494 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
495 List<String> methPrmTypes, String method) {
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) {
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) {
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;");
532 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
533 println("return (" + retType + ")retObj;");
540 * HELPER: returnGenericCallbackType() returns the callback type
542 private String returnGenericCallbackType(String paramType) {
544 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
545 return getTypeOfGeneric(paramType)[0];
552 * HELPER: checkCallbackType() checks the callback type
554 private boolean checkCallbackType(String paramType, String callbackType) {
556 String prmType = returnGenericCallbackType(paramType);
557 return callbackType.equals(prmType);
562 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
564 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
565 List<String> methPrmTypes, String method, String callbackType) {
568 // Check if this is single object, array, or list of objects
569 for (int i = 0; i < methParams.size(); i++) {
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++);");
578 println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(" +
579 getSimpleIdentifier(param) + ", objIdCnt++);");
580 println("listCallbackObj.add(skel);");
581 if (isArrayOrList(paramType, param))
585 println("} catch (Exception ex) {");
586 println("ex.printStackTrace();");
587 println("throw new Error(\"Exception when generating skeleton objects!\");");
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
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");
602 if (i != methParams.size() - 1) // Check if this is the last element
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()");
616 print("new Integer(1)");
618 print(getSimpleIdentifier(methParams.get(i)));
619 if (i != methParams.size() - 1)
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;");
634 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
635 println("return (" + retType + ")retObj;");
642 * HELPER: writeMethodJavaStub() writes the method of the stub class
644 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
646 for (String method : methods) {
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++) {
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
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) {
670 // Now, write the body of stub!
671 if (isCallbackMethod)
672 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
674 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method);
676 // Write the init callback helper method
677 if (isCallbackMethod)
678 writeInitCallbackJavaStub(callbackType, intDecl);
684 * generateJavaStubClasses() generate stubs based on the methods list in Java
686 public void generateJavaStubClasses() throws IOException {
688 // Create a new directory
689 String path = createDirectories(dir, subdir);
690 for (String intface : mapIntfacePTH.keySet()) {
692 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
693 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
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");
714 writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses);
716 writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses);
718 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
721 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
728 * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class
730 private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
732 println("private IoTRMICall rmiCall;");
733 println("private String address;");
734 println("private int[] ports;\n");
736 println("private static int objectId = 0;");
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 = { ");
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) {
767 println("private List<Integer> set" + newObjectId + "Allowed;");
775 * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class
777 private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
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;");
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);");
792 println("listCallbackObj = new ArrayList<" + callbackType + ">();");
793 println("___initCallBack();");
794 println("// TODO: Add address and port initialization here if we want callback in callback!");
801 * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java
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.
807 public void generateJavaCallbackStubClasses() throws IOException {
809 // Create a new directory
810 String path = createDirectories(dir, subdir);
811 for (String intface : mapIntfacePTH.keySet()) {
813 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
814 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
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");
835 writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses);
837 writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses);
839 // TODO: perhaps need to generate callback for callback
840 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
843 System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java...");
850 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
852 private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) {
854 println("private " + intface + " mainObj;");
855 //println("private int ports;");
856 println("private IoTRMIObject rmiObj;\n");
859 println("private static int objIdCnt = 0;");
860 println("private IoTRMICall rmiCall;");
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 = { ");
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) {
882 println("private List<Integer> set" + newObjectId + "Allowed;");
889 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
891 private void writeConstructorJavaSkeleton(String newSkelClass, String intface) {
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);");
903 println("___waitRequestInvokeMethod();");
909 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
911 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
913 if (methodType.equals("void"))
914 print("mainObj." + methodId + "(");
916 print("return mainObj." + methodId + "(");
917 for (int i = 0; i < methParams.size(); i++) {
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) {
930 * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class
932 private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton) {
934 // This is a callback skeleton generation
935 if (callbackSkeleton)
936 println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {");
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]);");
947 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
949 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses,
950 boolean callbackSkeleton) {
952 for (String method : methods) {
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++) {
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;
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) {
975 // Now, write the body of skeleton!
976 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
978 if (isCallbackMethod)
979 writeInitCallbackJavaSkeleton(callbackSkeleton);
985 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
987 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
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
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 + ">();");
1006 println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1007 println("objIdCnt++;");
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++;");
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++;");
1024 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1027 return mapStubParam;
1032 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
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++) {
1042 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1043 if (callbackClasses.contains(paramType)) {
1044 isCallbackMethod = true;
1045 callbackType = paramType;
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");
1051 if (i != methParams.size() - 1)
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");
1063 if (i != methParams.size() - 1)
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) + "(");
1077 for (int i = 0; i < methParams.size(); i++) {
1079 if (isCallbackMethod) {
1080 print(mapStubParam.get(i)); // Get the callback parameter
1082 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1083 print("(" + prmType + ") paramObj[" + i + "]");
1085 if (i != methParams.size() - 1)
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!\");");
1101 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1103 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1105 // Use this set to handle two same methodIds
1106 Set<String> uniqueMethodIds = new HashSet<String>();
1107 for (String method : methods) {
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);
1117 uniqueMethodIds.add(methodId);
1118 // Check if this is "void"
1119 String retType = intDecl.getMethodType(method);
1120 if (retType.equals("void"))
1121 println(helperMethod + "() {");
1123 println(helperMethod + "() throws IOException {");
1124 // Now, write the helper body of skeleton!
1125 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1132 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
1134 private void writeJavaMethodPermission(String intface) {
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);");
1146 println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");");
1154 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
1156 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
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;
1178 uniqueMethodIds.add(methodId);
1179 println(helperMethod + "(); break;");
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;");
1187 println("default: ");
1188 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
1196 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
1198 public void generateJavaSkeletonClass() throws IOException {
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
1220 println("public class " + newSkelClass + " implements " + intface + " {\n");
1222 writePropertiesJavaSkeleton(intface, callbackExist, intDecl);
1223 // Write constructor
1224 writeConstructorJavaSkeleton(newSkelClass, intface);
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);
1233 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
1239 * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class
1241 private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) {
1243 println("private " + intface + " mainObj;");
1244 // For callback skeletons, this is its own object Id
1245 println("private static int objectId = 0;");
1247 if (callbackExist) {
1248 println("private static int objIdCnt = 0;");
1249 println("private IoTRMICall rmiCall;");
1256 * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class
1258 private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface) {
1260 println("public " + newSkelClass + "(" + intface + " _mainObj, int _objectId) throws Exception {");
1261 println("mainObj = _mainObj;");
1262 println("objectId = _objectId;");
1268 * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class
1270 private void writeMethodHelperJavaCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1272 // Use this set to handle two same methodIds
1273 Set<String> uniqueMethodIds = new HashSet<String>();
1274 for (String method : methods) {
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);
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) {");
1290 println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {");
1291 // Now, write the helper body of skeleton!
1292 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1299 * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class
1301 private void writeJavaCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
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;
1319 uniqueMethodIds.add(methodId);
1320 println(helperMethod + "(rmiObj); break;");
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;");
1328 println("default: ");
1329 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
1336 * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java
1338 public void generateJavaCallbackSkeletonClass() throws IOException {
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
1360 println("public class " + newSkelClass + " implements " + intface + " {\n");
1362 writePropertiesJavaCallbackSkeleton(intface, callbackExist);
1363 // Write constructor
1364 writeConstructorJavaCallbackSkeleton(newSkelClass, intface);
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);
1373 System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java...");
1379 * HELPER: writeMethodCplusLocalInterface() writes the method of the interface
1381 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
1383 for (String method : methods) {
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) {
1408 * HELPER: writeMethodCplusInterface() writes the method of the interface
1410 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
1412 for (String method : methods) {
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) {
1437 * HELPER: writeEnumCplus() writes the enumeration declaration
1439 private void writeEnumCplus(EnumDecl enumDecl) {
1441 Set<String> enumTypes = enumDecl.getEnumDeclarations();
1442 // Iterate over enum declarations
1443 for (String enType : enumTypes) {
1445 println("enum " + enType + " {");
1446 List<String> enumMembers = enumDecl.getMembers(enType);
1447 for (int i = 0; i < enumMembers.size(); i++) {
1449 String member = enumMembers.get(i);
1451 // Check if this is the last element (don't print a comma)
1452 if (i != enumMembers.size() - 1)
1463 * HELPER: writeStructCplus() writes the struct declaration
1465 private void writeStructCplus(StructDecl structDecl) {
1467 List<String> structTypes = structDecl.getStructTypes();
1468 // Iterate over enum declarations
1469 for (String stType : structTypes) {
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++) {
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 + ";");
1488 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
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.
1495 public void generateCplusLocalInterfaces() throws IOException {
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("{");
1523 writeMethodCplusLocalInterface(methods, intDecl);
1527 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
1533 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
1535 * For C++ we use virtual classe as interface
1537 public void generateCPlusInterfaces() throws IOException {
1539 // Create a new directory
1540 String path = createDirectories(dir, subdir);
1541 for (String intface : mapIntfacePTH.keySet()) {
1543 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1544 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
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);
1566 writeMethodCplusInterface(intMeth.getValue(), intDecl);
1570 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
1577 * HELPER: writeMethodCplusStub() writes the method of the stub
1579 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1581 for (String method : methods) {
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++) {
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
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) {
1607 if (isCallbackMethod)
1608 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
1610 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method);
1612 // Write the init callback helper method
1613 if (isCallbackMethod) {
1614 writeInitCallbackCplusStub(callbackType, intDecl);
1615 writeInitCallbackSendInfoCplusStub(intDecl);
1622 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
1624 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
1625 List<String> methPrmTypes, String method, String callbackType) {
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++) {
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);
1641 println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(" +
1642 getSimpleIdentifier(param) + ", objIdCnt++);");
1643 println("vecCallbackObj.push_back(skel);");
1644 if (isArrayOrList(paramType, param))
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
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 + "\"");
1664 if (i != methParams.size() - 1) // Check if this is the last element
1668 print("int ___paramCB = ");
1670 println(callbackParam + ".size();");
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");
1680 print(getSimpleIdentifier(methParams.get(i)));
1681 if (i != methParams.size() - 1)
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;");
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;");
1702 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
1704 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
1705 List<String> methPrmTypes, String method) {
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) {
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) {
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;");
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;");
1751 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
1753 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
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;");
1786 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
1788 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
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();");
1808 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
1810 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1812 println("~" + newStubClass + "() {");
1813 println("if (rmiCall != NULL) {");
1814 println("delete rmiCall;");
1815 println("rmiCall = NULL;");
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;");
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;");
1836 * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
1838 private void writeCplusMethodCallbackPermission(String intface) {
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);");
1855 * HELPER: writeInitCallbackCplusStub() writes the initialization of callback
1857 private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl) {
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);");
1881 * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization of callback
1883 private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) {
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);");
1901 * generateCPlusStubClasses() generate stubs based on the methods list in C++
1903 public void generateCPlusStubClasses() throws IOException {
1905 // Create a new directory
1906 String path = createDirectories(dir, subdir);
1907 for (String intface : mapIntfacePTH.keySet()) {
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);
1939 writeMethodCplusStub(methods, intDecl, callbackClasses);
1940 print("}"); println(";");
1942 writePermissionInitializationCplus(intface, newStubClass, intDecl);
1945 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
1952 * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class
1954 private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
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;");
1983 * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class
1985 private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
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();");
2002 * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++
2004 public void generateCPlusCallbackStubClasses() throws IOException {
2006 // Create a new directory
2007 String path = createDirectories(dir, subdir);
2008 for (String intface : mapIntfacePTH.keySet()) {
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>");
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);
2040 writeMethodCplusStub(methods, intDecl, callbackClasses);
2043 writePermissionInitializationCplus(intface, newStubClass, intDecl);
2046 System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp...");
2053 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
2055 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
2057 println(intface + " *mainObj;");
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;");
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;");
2082 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
2084 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
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();
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) {
2109 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
2111 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist) {
2113 println(newSkelClass + "(" + intface + " *_mainObj, int _port) {");
2114 println("bool _bResult = false;");
2115 println("mainObj = _mainObj;");
2116 println("rmiObj = new IoTRMIObject(_port, &_bResult);");
2118 if (callbackExist) {
2119 println("objIdCnt = 0;");
2121 //println("set0Allowed = Arrays.asList(object0Permission);");
2122 println("___waitRequestInvokeMethod();");
2128 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
2130 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
2132 println("~" + newSkelClass + "() {");
2133 println("if (rmiObj != NULL) {");
2134 println("delete rmiObj;");
2135 println("rmiObj = NULL;");
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;");
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;");
2157 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
2159 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
2161 if (methodType.equals("void"))
2162 print("mainObj->" + methodId + "(");
2164 print("return mainObj->" + methodId + "(");
2165 for (int i = 0; i < methParams.size(); i++) {
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) {
2178 * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class
2180 private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton) {
2182 // This is a callback skeleton generation
2183 if (callbackSkeleton)
2184 println("void ___regCB(IoTRMIObject* rmiObj) {");
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[] = { ¶m1, ¶m2, ¶m3 };");
2192 println("bool bResult = false;");
2193 println("rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);");
2199 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
2201 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
2202 Set<String> callbackClasses, boolean callbackSkeleton) {
2204 for (String method : methods) {
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++) {
2215 String origParamType = methPrmTypes.get(i);
2216 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
2217 isCallbackMethod = true;
2218 callbackType = origParamType;
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) {
2230 // Now, write the body of skeleton!
2231 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
2233 if (isCallbackMethod)
2234 writeInitCallbackCplusSkeleton(callbackSkeleton);
2240 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
2242 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
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;");
2258 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
2260 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
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++;");
2278 println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
2279 println("vecCallbackObj.push_back(stub" + i + ");");
2280 println("objIdCnt++;");
2288 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
2290 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
2291 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
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;
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 + "\"");
2308 if (i != methParams.size() - 1) {
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 + ";");
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);
2332 print("&" + getSimpleIdentifier(methParams.get(i)));
2333 if (i != methParams.size() - 1) {
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))
2350 print(getSimpleIdentifier(methParams.get(i)));
2351 if (i != methParams.size() - 1) {
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))
2363 print(getSimpleIdentifier(methParams.get(i)));
2364 if (i != methParams.size() - 1) {
2369 println("void* retObj = &retVal;");
2370 String retTypeC = checkAndGetCplusType(retType);
2371 println("rmiObj->sendReturnObj(retObj, \"" + checkAndGetCplusArrayType(retTypeC) + "\");");
2377 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
2379 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2381 // Use this set to handle two same methodIds
2382 Set<String> uniqueMethodIds = new HashSet<String>();
2383 for (String method : methods) {
2385 List<String> methParams = intDecl.getMethodParams(method);
2386 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2387 String methodId = intDecl.getMethodId(method);
2389 String helperMethod = methodId;
2390 if (uniqueMethodIds.contains(methodId))
2391 helperMethod = helperMethod + intDecl.getMethodNumId(method);
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);
2405 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
2407 private void writeCplusMethodPermission(String intface) {
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);");
2420 println("cerr << \"Object Id: \" << _objectId << \" not recognized!\" << endl;");
2421 println("exit(-1);");
2429 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
2431 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
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;
2453 uniqueMethodIds.add(methodId);
2454 println(helperMethod + "(); break;");
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;");
2462 println("default: ");
2463 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
2464 println("throw exception();");
2472 * generateCplusSkeletonClass() generate skeletons based on the methods list in C++
2474 public void generateCplusSkeletonClass() throws IOException {
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");
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);
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);
2517 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
2520 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
2526 * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class
2528 private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
2530 println(intface + " *mainObj;");
2531 // Keep track of object Ids of all stubs registered to this interface
2532 println("static int objectId;");
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;");
2548 * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class
2550 private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist) {
2552 println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {");
2553 println("mainObj = _mainObj;");
2554 println("objectId = _objectId;");
2556 if (callbackExist) {
2557 println("objIdCnt = 0;");
2564 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
2566 private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist,
2567 Set<String> callbackClasses) {
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;");
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;");
2590 * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of the callback skeleton class
2592 private void writeMethodHelperCplusCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl,
2593 Set<String> callbackClasses) {
2595 // Use this set to handle two same methodIds
2596 Set<String> uniqueMethodIds = new HashSet<String>();
2597 for (String method : methods) {
2599 List<String> methParams = intDecl.getMethodParams(method);
2600 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2601 String methodId = intDecl.getMethodId(method);
2603 String helperMethod = methodId;
2604 if (uniqueMethodIds.contains(methodId))
2605 helperMethod = helperMethod + intDecl.getMethodNumId(method);
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);
2619 * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class
2621 private void writeCplusCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
2622 boolean callbackExist) {
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;
2640 uniqueMethodIds.add(methodId);
2641 println(helperMethod + "(rmiObj); break;");
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;");
2649 println("default: ");
2650 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
2651 println("throw exception();");
2659 * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++
2661 public void generateCplusCallbackSkeletonClass() throws IOException {
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");
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);
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);
2706 System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp...");
2712 * generateInitializer() generate initializer based on type
2714 public String generateCplusInitializer(String type) {
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")) {
2724 } else if ( type.equals("String") ||
2725 type.equals("string")) {
2728 } else if ( type.equals("char") ||
2729 type.equals("byte")) {
2732 } else if ( type.equals("boolean")) {
2742 * generateReturnStmt() generate return statement based on methType
2744 public String generateReturnStmt(String methType) {
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")) {
2754 } else if ( methType.equals("String")) {
2757 } else if ( methType.equals("char") ||
2758 methType.equals("byte")) {
2761 } else if ( methType.equals("boolean")) {
2771 * setDirectory() sets a new directory for stub files
2773 public void setDirectory(String _subdir) {
2780 * printUsage() prints the usage of this compiler
2782 public static void printUsage() {
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();
2802 * parseFile() prepares Lexer and Parser objects, then parses the file
2804 public static ParseNode parseFile(String file) {
2806 ParseNode pn = null;
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);
2826 boolean newline=true;
2829 private void print(String str) {
2832 if (str.equals("}"))
2834 for(int i=0; i<tab; i++)
2844 * This function converts Java to C++ type for compilation
2846 private String convertType(String jType) {
2848 return mapPrimitives.get(jType);
2852 private void println(String str) {
2855 if (str.contains("}") && !str.contains("{"))
2857 for(int i=0; i<tab; i++)
2866 private void updatetabbing(String str) {
2868 tablevel+=count(str,'{')-count(str,'}');
2872 private int count(String str, char key) {
2873 char[] array = str.toCharArray();
2875 for(int i=0; i<array.length; i++) {
2876 if (array[i] == key)
2883 private void createDirectory(String dirName) {
2885 File file = new File(dirName);
2886 if (!file.exists()) {
2888 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
2890 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
2893 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
2898 // Create a directory and possibly a sub directory
2899 private String createDirectories(String dir, String subdir) {
2902 createDirectory(path);
2903 if (subdir != null) {
2904 path = path + "/" + subdir;
2905 createDirectory(path);
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) {
2915 for(int i = 0; i < arrKey.length; i++) {
2917 map.put(arrKey[i], arrVal[i]);
2922 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
2923 private ParamCategory getParamCategory(String paramType) {
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;
2931 return ParamCategory.USERDEFINED;
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) {
2939 return mapNonPrimitivesJava.get(paramNonPrimitives);
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) {
2947 return mapNonPrimitivesCplus.get(paramNonPrimitives);
2951 // Get simple types, e.g. HashSet for HashSet<...>
2952 // Basically strip off the "<...>"
2953 private String getSimpleType(String paramType) {
2955 // Check if this is generics
2956 if(paramType.contains("<")) {
2957 String[] type = paramType.split("<");
2964 // Generate a set of standard classes for import statements
2965 private List<String> getStandardJavaImportClasses() {
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");
2976 return importClasses;
2980 // Generate a set of standard classes for import statements
2981 private List<String> getStandardCplusIncludeClasses() {
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\"");
2990 return importClasses;
2994 // Generate a set of standard classes for import statements
2995 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
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);
3005 return allLibClasses;
3010 // Generate a set of classes for import statements
3011 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
3013 Set<String> importClasses = new HashSet<String>();
3014 for (String method : methods) {
3015 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3016 for (String paramType : methPrmTypes) {
3018 String simpleType = getSimpleType(paramType);
3019 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
3020 importClasses.add(getNonPrimitiveJavaClass(simpleType));
3024 return importClasses;
3028 // Generate a set of classes for include statements
3029 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, boolean needExchange) {
3031 Set<String> includeClasses = new HashSet<String>();
3032 for (String method : methods) {
3034 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3035 List<String> methParams = intDecl.getMethodParams(method);
3036 for (int i = 0; i < methPrmTypes.size(); i++) {
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
3045 includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
3046 includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\"");
3048 includeClasses.add("\"" + simpleType + ".hpp\"");
3049 includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\"");
3051 } else if (param.contains("[]")) {
3052 // Check if this is array for C++; translate into vector
3053 includeClasses.add("<vector>");
3057 return includeClasses;
3061 // Generate a set of callback classes
3062 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
3064 Set<String> callbackClasses = new HashSet<String>();
3065 for (String method : methods) {
3067 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3068 List<String> methParams = intDecl.getMethodParams(method);
3069 for (int i = 0; i < methPrmTypes.size(); i++) {
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);
3083 return callbackClasses;
3087 private void printImportStatements(Collection<String> importClasses) {
3089 for(String cls : importClasses) {
3090 println("import " + cls + ";");
3095 private void printIncludeStatements(Collection<String> includeClasses) {
3097 for(String cls : includeClasses) {
3098 println("#include " + cls);
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) {
3108 // Handle <, >, and , for 2-type generic/template
3109 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
3114 // This helper function strips off array declaration, e.g. D[] becomes D
3115 private String getSimpleIdentifier(String ident) {
3117 // Handle [ for array declaration
3118 String substr = ident;
3119 if (ident.contains("[]")) {
3120 substr = ident.split("\\[\\]")[0];
3126 private String checkAndGetCplusType(String paramType) {
3128 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
3129 return convertType(paramType);
3130 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
3132 // Check for generic/template format
3133 if (paramType.contains("<") && paramType.contains(">")) {
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;
3146 return getNonPrimitiveCplusClass(paramType);
3147 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
3148 return paramType + "*";
3150 // Just return it as is if it's not non-primitives
3152 //return checkAndGetParamClass(paramType, true);
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) {
3160 String paramComplete = null;
3161 // Check for array declaration
3162 if (param.contains("[]")) {
3163 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
3165 // Just return it as is if it's not an array
3166 paramComplete = paramType + " " + param;
3168 return paramComplete;
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) {
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) + "[]";
3187 paramTypeRet = paramType;
3189 return paramTypeRet;
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) {
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) + "[]";
3207 paramTypeRet = paramType;
3209 return paramTypeRet;
3213 // Detect array declaration, e.g. int A[],
3214 // then generate type "int[]"
3215 private String checkAndGetArray(String paramType, String param) {
3217 String paramTypeRet = null;
3218 // Check for array declaration
3219 if (param.contains("[]")) {
3220 paramTypeRet = paramType + "[]";
3222 // Just return it as is if it's not an array
3223 paramTypeRet = paramType;
3225 return paramTypeRet;
3229 // Is array or list?
3230 private boolean isArrayOrList(String paramType, String param) {
3232 // Check for array declaration
3233 if (isArray(paramType, param))
3235 else if (isList(paramType, param))
3242 // Is array or list?
3243 private boolean isArray(String paramType, String param) {
3245 // Check for array declaration
3246 if (param.contains("[]"))
3253 // Is array or list?
3254 private boolean isList(String paramType, String param) {
3256 // Check for array declaration
3257 if (paramType.contains("List"))
3264 // Get the right type for a callback object
3265 private String checkAndGetParamClass(String paramType) {
3267 // Check if this is generics
3268 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
3269 return exchangeParamType(paramType);
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) {
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();
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!");
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++).");
3307 public static void main(String[] args) throws Exception {
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)) {
3315 IoTCompiler.printUsage();
3317 } else if (args.length > 1) {
3319 IoTCompiler comp = new IoTCompiler();
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);
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") &&
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();
3352 // Check other options
3353 while(i < args.length) {
3355 if (!args[i].equals("-java") &&
3356 !args[i].equals("-cplus")) {
3357 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
3359 if (i + 1 < args.length) {
3360 comp.setDirectory(args[i+1]);
3362 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
3364 if (args[i].equals("-java")) {
3365 comp.generateJavaLocalInterfaces();
3366 comp.generateJavaInterfaces();
3367 comp.generateJavaStubClasses();
3368 comp.generateJavaCallbackStubClasses();
3369 comp.generateJavaSkeletonClass();
3370 comp.generateJavaCallbackSkeletonClass();
3372 comp.generateCplusLocalInterfaces();
3373 comp.generateCPlusInterfaces();
3374 comp.generateCPlusStubClasses();
3375 comp.generateCPlusCallbackStubClasses();
3376 comp.generateCplusSkeletonClass();
3377 comp.generateCplusCallbackSkeletonClass();
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!");