3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
15 import iotpolicy.parser.Lexer;
16 import iotpolicy.parser.Parser;
17 import iotpolicy.tree.ParseNode;
18 import iotpolicy.tree.ParseNodeVector;
19 import iotpolicy.tree.ParseTreeHandler;
20 import iotpolicy.tree.Declaration;
21 import iotpolicy.tree.DeclarationHandler;
22 import iotpolicy.tree.CapabilityDecl;
23 import iotpolicy.tree.InterfaceDecl;
24 import iotpolicy.tree.RequiresDecl;
26 import iotrmi.Java.IoTRMITypes;
29 /** Class IoTCompiler is the main interface/stub compiler for
30 * files generation. This class calls helper classes
31 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
32 * RequiresDecl, ParseTreeHandler, etc.
34 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
38 public class IoTCompiler {
43 // Maps multiple interfaces to multiple objects of ParseTreeHandler
44 private Map<String,ParseTreeHandler> mapIntfacePTH;
45 private Map<String,DeclarationHandler> mapIntDeclHand;
46 private Map<String,Map<String,Set<String>>> mapInt2NewInts;
47 // Data structure to store our types (primitives and non-primitives) for compilation
48 private Map<String,String> mapPrimitives;
49 private Map<String,String> mapNonPrimitivesJava;
50 private Map<String,String> mapNonPrimitivesCplus;
51 private PrintWriter pw;
53 private String subdir;
58 private final static String OUTPUT_DIRECTORY = "output_files";
60 private enum ParamCategory {
62 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
63 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
64 USERDEFINED // Non-supported type by default; assumed as driver classes
70 public IoTCompiler() {
72 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
73 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
74 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
75 mapPrimitives = new HashMap<String,String>();
76 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
77 mapNonPrimitivesJava = new HashMap<String,String>();
78 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
79 mapNonPrimitivesCplus = new HashMap<String,String>();
80 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
82 dir = OUTPUT_DIRECTORY;
88 * setParseTree() sets parse tree based on policy files.
90 * It also generates parse tree (ParseTreeHandler) and
91 * copies useful information from parse tree into
92 * InterfaceDecl, CapabilityDecl, and RequiresDecl
94 * Additionally, the data structure handles are
95 * returned from tree-parsing for further process.
98 public void setParseTree(String origInt, ParseNode pnPol, ParseNode pnReq) {
100 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
101 DeclarationHandler decHandler = new DeclarationHandler();
103 // Process ParseNode and generate Declaration objects
104 ptHandler.processInterfaceDecl();
105 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
106 decHandler.addInterfaceDecl(origInt, intDecl);
107 ptHandler.processCapabilityDecl();
108 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
109 decHandler.addCapabilityDecl(origInt, capDecl);
110 ptHandler.processRequiresDecl();
111 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
112 decHandler.addRequiresDecl(origInt, reqDecl);
114 mapIntfacePTH.put(origInt, ptHandler);
115 mapIntDeclHand.put(origInt, decHandler);
120 * getMethodsForIntface() reads for methods in the data structure
122 * It is going to give list of methods for a certain interface
123 * based on the declaration of capabilities.
125 public void getMethodsForIntface(String origInt) {
127 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
128 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
129 // Get set of new interfaces, e.g. CameraWithCaptureAndData
130 // Generate this new interface with all the methods it needs
131 // from different capabilities it declares
132 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
133 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
134 Set<String> setIntfaces = reqDecl.getInterfaces();
135 for (String strInt : setIntfaces) {
137 // Initialize a set of methods
138 Set<String> setMethods = new HashSet<String>();
139 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
140 List<String> listCapab = reqDecl.getCapabList(strInt);
141 for (String strCap : listCapab) {
143 // Get list of methods for each capability
144 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
145 List<String> listCapabMeth = capDecl.getMethods(strCap);
146 for (String strMeth : listCapabMeth) {
148 // Add methods into setMethods
149 // This is to also handle redundancies (say two capabilities
150 // share the same methods)
151 setMethods.add(strMeth);
154 // Add interface and methods information into map
155 mapNewIntMethods.put(strInt, setMethods);
157 // Map the map of interface-methods to the original interface
158 mapInt2NewInts.put(origInt, mapNewIntMethods);
163 * generateJavaLocalInterface() writes the local interface and provides type-checking.
165 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
166 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
167 * The local interface has to be the input parameter for the stub and the stub
168 * interface has to be the input parameter for the local class.
170 public void generateJavaLocalInterfaces() throws IOException {
172 // Create a new directory
173 createDirectory(dir);
174 for (String intface : mapIntfacePTH.keySet()) {
175 // Open a new file to write into
176 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
177 pw = new PrintWriter(new BufferedWriter(fw));
178 // Pass in set of methods and get import classes
179 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
180 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
181 List<String> methods = intDecl.getMethods();
182 Set<String> importClasses = getImportClasses(methods, intDecl);
183 printImportStatements(importClasses);
184 // Write interface header
186 println("public interface " + intface + " {");
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), false);
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) {
208 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
214 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
216 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
217 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
218 * The local interface has to be the input parameter for the stub and the stub
219 * interface has to be the input parameter for the local class.
221 public void generateCplusLocalInterfaces() throws IOException {
223 // Create a new directory
224 createDirectory(dir);
225 for (String intface : mapIntfacePTH.keySet()) {
226 // Open a new file to write into
227 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
228 pw = new PrintWriter(new BufferedWriter(fw));
229 // Write file headers
230 println("#include <iostream>");
231 // Pass in set of methods and get include classes
232 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
233 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
234 List<String> methods = intDecl.getMethods();
237 Set<String> includeClasses = getIncludeClasses(methods, intDecl);
239 printIncludeStatements(includeClasses);
241 println("using namespace std;");
243 println("class " + intface);
247 for (String method : methods) {
249 List<String> methParams = intDecl.getMethodParams(method);
250 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
251 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
252 intDecl.getMethodId(method) + "(");
253 for (int i = 0; i < methParams.size(); i++) {
254 // Check for params with driver class types and exchange it
255 // with its remote interface
256 String paramType = checkAndGetParamClass(methPrmTypes.get(i), true);
257 paramType = checkAndGetCplusType(paramType);
258 // Check for arrays - translate into vector in C++
259 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
260 //print(paramType + " " + param);
261 print(paramComplete);
262 // Check if this is the last element (don't print a comma)
263 if (i != methParams.size() - 1) {
272 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
278 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
280 public void generateJavaInterfaces() throws IOException {
282 // Create a new directory
283 String path = createDirectories(dir, subdir);
284 for (String intface : mapIntfacePTH.keySet()) {
286 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
287 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
289 // Open a new file to write into
290 String newIntface = intMeth.getKey();
291 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
292 pw = new PrintWriter(new BufferedWriter(fw));
293 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
294 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
295 // Pass in set of methods and get import classes
296 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
297 printImportStatements(importClasses);
298 // Write interface header
300 println("public interface " + newIntface + " {");
301 List<String> meths = intDecl.getMethods();
303 for (String method : intMeth.getValue()) {
305 List<String> methParams = intDecl.getMethodParams(method);
306 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
307 print("public " + intDecl.getMethodType(method) + " " +
308 intDecl.getMethodId(method) + "(");
309 for (int i = 0; i < methParams.size(); i++) {
310 String paramType = checkAndGetParamClass(methPrmTypes.get(i), false);
311 print(paramType + " " + methParams.get(i));
312 //print(methPrmTypes.get(i) + " " + methParams.get(i));
313 // Check if this is the last element (don't print a comma)
314 if (i != methParams.size() - 1) {
322 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
329 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
331 * For C++ we use virtual classe as interface
333 public void generateCPlusInterfaces() throws IOException {
335 // Create a new directory
336 String path = createDirectories(dir, subdir);
337 for (String intface : mapIntfacePTH.keySet()) {
339 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
340 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
342 // Open a new file to write into
343 String newIntface = intMeth.getKey();
344 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
345 pw = new PrintWriter(new BufferedWriter(fw));
346 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
347 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
348 // Write file headers
349 println("#include <iostream>");
350 // Pass in set of methods and get import classes
351 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
352 printIncludeStatements(includeClasses);
354 println("using namespace std;");
356 println("class " + newIntface);
360 for (String method : intMeth.getValue()) {
362 List<String> methParams = intDecl.getMethodParams(method);
363 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
364 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
365 intDecl.getMethodId(method) + "(");
366 for (int i = 0; i < methParams.size(); i++) {
367 String methPrmType = checkAndGetParamClass(methPrmTypes.get(i), true);
368 methPrmType = checkAndGetCplusType(methPrmType);
369 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
370 print(methParamComplete);
371 // Check if this is the last element (don't print a comma)
372 if (i != methParams.size() - 1) {
381 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
388 * generateJavaStubClasses() generate stubs based on the methods list in Java
390 public void generateJavaStubClasses() throws IOException {
392 // Create a new directory
393 String path = createDirectories(dir, subdir);
394 for (String intface : mapIntfacePTH.keySet()) {
396 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
397 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
399 // Open a new file to write into
400 String newIntface = intMeth.getKey();
401 String newStubClass = newIntface + "_Stub";
402 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
403 pw = new PrintWriter(new BufferedWriter(fw));
404 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
405 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
406 // Pass in set of methods and get import classes
407 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
408 printImportStatements(importClasses);
409 // Write interface header
411 println("public class " + newStubClass + " implements " + newIntface + " {");
414 for (String method : intMeth.getValue()) {
416 List<String> methParams = intDecl.getMethodParams(method);
417 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
418 print("public " + intDecl.getMethodType(method) + " " +
419 intDecl.getMethodId(method) + "(");
420 for (int i = 0; i < methParams.size(); i++) {
422 print(methPrmTypes.get(i) + " " + methParams.get(i));
423 // Check if this is the last element (don't print a comma)
424 if (i != methParams.size() - 1) {
429 // Check if this is not "void"
430 if (!intDecl.getMethodType(method).equals("void")) {
431 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
432 println("return " + retStmt + ";");
434 println("}"); println("");
438 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
445 * generateCPlusStubClasses() generate stubs based on the methods list in C++
447 public void generateCPlusStubClasses() throws IOException {
449 // Create a new directory
450 String path = createDirectories(dir, subdir);
451 for (String intface : mapIntfacePTH.keySet()) {
453 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
454 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
455 // Open a new file to write into
456 String newIntface = intMeth.getKey();
457 String newStubClass = newIntface + "_Stub";
458 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
459 pw = new PrintWriter(new BufferedWriter(fw));
460 // Write file headers
461 println("#include <iostream>");
462 println("#include \"" + newIntface + ".hpp\""); println("");
463 println("using namespace std;"); println("");
464 println("class " + newStubClass + " : public " + newIntface); println("{");
465 println("public:"); println("");
466 // Add default constructor and destructor
467 println(newStubClass + "() { }"); println("");
468 println("~" + newStubClass + "() { }"); println("");
469 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
470 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
472 for (String method : intMeth.getValue()) {
474 List<String> methParams = intDecl.getMethodParams(method);
475 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
476 print(convertType(intDecl.getMethodType(method)) + " " +
477 intDecl.getMethodId(method) + "(");
478 for (int i = 0; i < methParams.size(); i++) {
479 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
480 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
481 print(methParamComplete);
482 // Check if this is the last element (don't print a comma)
483 if (i != methParams.size() - 1) {
488 // Check if this is not "void"
489 if (!intDecl.getMethodType(method).equals("void")) {
490 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
491 if (retStmt.equals("null")) { // null = NULL in C++
494 println("return " + retStmt + ";");
496 println("}"); println("");
498 print("}"); println(";");
500 System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
507 * generateReturnStmt() generate return statement based on methType
509 public String generateReturnStmt(String methType) {
511 // Generate dummy returns for now
512 if (methType.equals("short")||
513 methType.equals("int") ||
514 methType.equals("long") ||
515 methType.equals("float")||
516 methType.equals("double")) {
519 } else if ( methType.equals("String")) {
522 } else if ( methType.equals("char") ||
523 methType.equals("byte")) {
526 } else if ( methType.equals("boolean")) {
536 * setDirectory() sets a new directory for stub files
538 public void setDirectory(String _subdir) {
545 * printUsage() prints the usage of this compiler
547 public static void printUsage() {
549 System.out.println();
550 System.out.println("Sentinel interface and stub compiler version 1.0");
551 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
552 System.out.println("All rights reserved.");
553 System.out.println("Usage:");
554 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
555 System.out.println("\t\tDisplay this help texts\n\n");
556 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
557 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
558 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
559 System.out.println("Options:");
560 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
561 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
562 System.out.println();
567 * parseFile() prepares Lexer and Parser objects, then parses the file
569 public static ParseNode parseFile(String file) {
573 ComplexSymbolFactory csf = new ComplexSymbolFactory();
574 ScannerBuffer lexer =
575 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
576 Parser parse = new Parser(lexer,csf);
577 pn = (ParseNode) parse.parse().value;
578 } catch (Exception e) {
580 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
591 boolean newline=true;
594 private void print(String str) {
599 for(int i=0; i<tab; i++)
608 * This function converts Java to C++ type for compilation
610 private String convertType(String jType) {
612 return mapPrimitives.get(jType);
616 private void println(String str) {
621 for(int i=0; i<tab; i++)
630 private void updatetabbing(String str) {
631 tablevel+=count(str,'{')-count(str,'}');
635 private int count(String str, char key) {
636 char[] array = str.toCharArray();
638 for(int i=0; i<array.length; i++) {
646 private void createDirectory(String dirName) {
648 File file = new File(dirName);
649 if (!file.exists()) {
651 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
653 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
656 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
661 // Create a directory and possibly a sub directory
662 private String createDirectories(String dir, String subdir) {
665 createDirectory(path);
666 if (subdir != null) {
667 path = path + "/" + subdir;
668 createDirectory(path);
674 // Inserting array members into a Map object
675 // that maps arrKey to arrVal objects
676 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
678 for(int i = 0; i < arrKey.length; i++) {
680 map.put(arrKey[i], arrVal[i]);
685 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
686 private ParamCategory getParamCategory(String paramType) {
688 if (mapPrimitives.containsKey(paramType)) {
689 return ParamCategory.PRIMITIVES;
690 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
691 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
692 return ParamCategory.NONPRIMITIVES;
694 return ParamCategory.USERDEFINED;
698 // Return full class name for non-primitives to generate Java import statements
699 // e.g. java.util.Set for Set, java.util.Map for Map
700 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
702 return mapNonPrimitivesJava.get(paramNonPrimitives);
706 // Return full class name for non-primitives to generate Cplus include statements
707 // e.g. #include <set> for Set, #include <map> for Map
708 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
710 return mapNonPrimitivesCplus.get(paramNonPrimitives);
714 // Get simple types, e.g. HashSet for HashSet<...>
715 // Basically strip off the "<...>"
716 private String getSimpleType(String paramType) {
718 // Check if this is generics
719 if(paramType.contains("<")) {
720 String[] type = paramType.split("<");
727 // Generate a set of classes for import statements
728 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
730 Set<String> importClasses = new HashSet<String>();
731 for (String method : methods) {
732 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
733 for (String paramType : methPrmTypes) {
735 String simpleType = getSimpleType(paramType);
736 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
737 importClasses.add(getNonPrimitiveJavaClass(simpleType));
741 return importClasses;
745 // Generate a set of classes for include statements
746 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
748 Set<String> includeClasses = new HashSet<String>();
749 for (String method : methods) {
751 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
752 List<String> methParams = intDecl.getMethodParams(method);
753 for (int i = 0; i < methPrmTypes.size(); i++) {
755 String simpleType = getSimpleType(methPrmTypes.get(i));
756 String param = methParams.get(i);
757 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
758 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
759 } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
760 includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
761 } else if (param.contains("[]")) {
762 // Check if this is array for C++; translate into vector
763 includeClasses.add("<vector>");
767 return includeClasses;
771 private void printImportStatements(Set<String> importClasses) {
773 for(String cls : importClasses) {
774 println("import " + cls + ";");
779 private void printIncludeStatements(Set<String> includeClasses) {
781 for(String cls : includeClasses) {
782 println("#include " + cls);
787 // Get the C++ version of a non-primitive type
788 // e.g. set for Set and map for Map
789 // Input nonPrimitiveType has to be generics in format
790 private String[] getTypeOfGeneric(String nonPrimitiveType) {
792 // Handle <, >, and , for 2-type generic/template
793 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
798 private String checkAndGetCplusType(String paramType) {
800 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
801 return convertType(paramType);
802 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
804 // Check for generic/template format
805 if (paramType.contains("<") && paramType.contains(">")) {
807 String genericClass = getSimpleType(paramType);
808 String[] genericType = getTypeOfGeneric(paramType);
809 String cplusTemplate = null;
810 if (genericType.length == 1) // Generic/template with one type
811 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
812 "<" + convertType(genericType[0]) + ">";
813 else // Generic/template with two types
814 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
815 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
816 return cplusTemplate;
818 return getNonPrimitiveCplusClass(paramType);
820 // Just return it as is if it's not non-primitives
825 // Detect array declaration, e.g. int A[],
826 // then generate "int A[]" in C++ as "vector<int> A"
827 private String checkAndGetCplusArray(String paramType, String param) {
829 String paramComplete = null;
830 // Check for array declaration
831 if (param.contains("[]")) {
832 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
834 // Just return it as is if it's not an array
835 paramComplete = paramType + " " + param;
837 return paramComplete;
841 // Get simple types, e.g. HashSet for HashSet<...>
842 // Basically strip off the "<...>"
843 private String checkAndGetParamClass(String paramType, boolean needPtr) {
845 // Check if this is generics
846 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
847 // If true then return with pointer (C++)
849 return exchangeParamType(paramType) + "*";
850 else // Java, so no pointer needed
851 return exchangeParamType(paramType);
857 // Returns the other interface for type-checking purposes for USERDEFINED
858 // classes based on the information provided in multiple policy files
859 // e.g. return CameraWithXXX instead of Camera
860 private String exchangeParamType(String intface) {
862 // Param type that's passed is the interface name we need to look for
863 // in the map of interfaces, based on available policy files.
864 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
865 if (decHandler != null) {
866 // We've found the required interface policy files
867 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
868 Set<String> setExchInt = reqDecl.getInterfaces();
869 if (setExchInt.size() == 1) {
870 Iterator iter = setExchInt.iterator();
871 return (String) iter.next();
873 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
874 ". Only one new interface can be declared if the object " + intface +
875 " needs to be passed in as an input parameter!");
878 // NULL value - this means policy files missing
879 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
880 "... Please provide the necessary policy files for user-defined types." +
881 " If this is an array please type the brackets after the variable name," +
882 " e.g. \"String str[]\", not \"String[] str\"." +
883 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
884 " supports List/ArrayList (Java) or list (C++).");
889 public static void main(String[] args) throws Exception {
891 // If there is no argument or just "--help" or "-h", then invoke printUsage()
892 if ((args[0].equals("-help") ||
893 args[0].equals("--help")||
894 args[0].equals("-h")) ||
895 (args.length == 0)) {
897 IoTCompiler.printUsage();
899 } else if (args.length > 1) {
901 IoTCompiler comp = new IoTCompiler();
904 // Parse main policy file
905 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
906 // Parse "requires" policy file
907 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
908 // Get interface name
909 String intface = ParseTreeHandler.getOrigIntface(pnPol);
910 comp.setParseTree(intface, pnPol, pnReq);
911 comp.getMethodsForIntface(intface);
913 // 1) Check if this is the last option before "-java" or "-cplus"
914 // 2) Check if this is really the last option (no "-java" or "-cplus")
915 } while(!args[i].equals("-java") &&
916 !args[i].equals("-cplus") &&
919 // Generate everything if we don't see "-java" or "-cplus"
920 if (i == args.length) {
921 comp.generateJavaLocalInterfaces();
922 comp.generateJavaInterfaces();
923 comp.generateJavaStubClasses();
924 comp.generateCplusLocalInterfaces();
925 comp.generateCPlusInterfaces();
926 comp.generateCPlusStubClasses();
928 // Check other options
929 while(i < args.length) {
931 if (!args[i].equals("-java") &&
932 !args[i].equals("-cplus")) {
933 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
935 if (i + 1 < args.length) {
936 comp.setDirectory(args[i+1]);
938 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
940 if (args[i].equals("-java")) {
941 comp.generateJavaLocalInterfaces();
942 comp.generateJavaInterfaces();
943 comp.generateJavaStubClasses();
945 comp.generateCplusLocalInterfaces();
946 comp.generateCPlusInterfaces();
947 comp.generateCPlusStubClasses();
954 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
955 IoTCompiler.printUsage();
956 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");