3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
6 import java.util.HashMap;
7 import java.util.HashSet;
12 import iotpolicy.parser.Lexer;
13 import iotpolicy.parser.Parser;
14 import iotpolicy.tree.ParseNode;
15 import iotpolicy.tree.ParseNodeVector;
16 import iotpolicy.tree.ParseTreeHandler;
17 import iotpolicy.tree.CapabilityDecl;
18 import iotpolicy.tree.InterfaceDecl;
19 import iotpolicy.tree.RequiresDecl;
21 /** Class IoTStubCompiler is the main stub compiler for
22 * stub files generation. This class calls helper classes
23 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
24 * RequiresDecl, ParseTreeHandler, etc.
26 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
30 public final class IoTStubCompiler {
35 private String origInt;
36 private ParseTreeHandler ptHandler;
37 private InterfaceDecl intDecl;
38 private CapabilityDecl capDecl;
39 private RequiresDecl reqDecl;
40 private Map<String,Set<String>> mapCapabMethods;
41 private PrintWriter pw;
47 private final static String OUTPUT_DIRECTORY = "stubfiles";
52 public IoTStubCompiler() {
55 ptHandler = new ParseTreeHandler();
59 mapCapabMethods = new HashMap<String,Set<String>>();
61 dir = OUTPUT_DIRECTORY;
65 public IoTStubCompiler(String _origInt, ParseNode _pn) {
68 ptHandler = new ParseTreeHandler(_origInt, _pn);
72 mapCapabMethods = new HashMap<String,Set<String>>();
74 dir = OUTPUT_DIRECTORY;
79 * parsePolicyFile() parses policy file
81 * It also generates parse tree and
82 * copies useful information from parse tree into
83 * InterfaceDecl, CapabilityDecl, and RequiresDecl
85 * Additionally, the data structure handles are
86 * returned from tree-parsing for further process.
89 public void parsePolicyFile() {
91 ptHandler.processInterfaceDecl();
92 intDecl = ptHandler.getInterfaceDecl();
94 ptHandler.processCapabilityDecl();
95 capDecl = ptHandler.getCapabilityDecl();
97 ptHandler.processRequiresDecl();
98 reqDecl = ptHandler.getRequiresDecl();
103 * getMethodsForIntface() reads for methods in the data structure
105 * It is going to give list of methods for a certain interface
106 * based on the declaration of capabilities.
108 public void getMethodsForIntface() {
110 // Get set of new interfaces, e.g. CameraWithCaptureAndData
111 // Generate this new interface with all the methods it needs
112 // from different capabilities it declares
113 Set<String> setIntfaces = reqDecl.getInterfaces();
114 for (String strInt : setIntfaces) {
116 // Initialize a set of methods
117 Set<String> setMethods = new HashSet<String>();
118 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
119 List<String> listCapab = reqDecl.getCapabList(strInt);
120 for (String strCap : listCapab) {
122 // Get list of methods for each capability
123 List<String> listCapabMeth = capDecl.getMethods(strCap);
124 for (String strMeth : listCapabMeth) {
126 // Add methods into setMethods
127 // This is to also handle redundancies (say two capabilities
128 // share the same methods)
129 setMethods.add(strMeth);
132 // Add interface and methods information into map
133 mapCapabMethods.put(strInt, setMethods);
139 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
141 public void generateJavaInterfaces() throws IOException {
143 // Create a new directory
144 createDirectory(dir);
145 for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
147 // Open a new file to write into
148 String newIntface = intMeth.getKey();
149 FileWriter fw = new FileWriter(dir + "/" + newIntface + ".java");
150 pw = new PrintWriter(new BufferedWriter(fw));
151 // Write interface header
153 println("public interface " + newIntface + " {");
155 for (String method : intMeth.getValue()) {
157 List<String> methParams = intDecl.getMethodParams(method);
158 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
159 print("public " + intDecl.getMethodType(method) + " " +
161 for (int i = 0; i < methParams.size(); i++) {
162 print(methPrmTypes.get(i) + " " + methParams.get(i));
163 // Check if this is the last element (don't print a comma)
164 if (i != methParams.size() - 1) {
172 System.out.println("IoTStubCompiler: Generated interface " + newIntface + ".java...");
178 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
180 * For C++ we use virtual classe as interface
182 public void generateCPlusInterfaces() throws IOException {
184 // Create a new directory
185 createDirectory(dir);
186 for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
188 // Open a new file to write into
189 String newIntface = intMeth.getKey();
190 FileWriter fw = new FileWriter(dir + "/" + newIntface + ".hpp");
191 pw = new PrintWriter(new BufferedWriter(fw));
192 // Write file headers
193 println("#include<iostream>");
195 println("using namespace std;");
197 println("class " + newIntface);
201 for (String method : intMeth.getValue()) {
203 List<String> methParams = intDecl.getMethodParams(method);
204 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
205 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
207 for (int i = 0; i < methParams.size(); i++) {
208 print(convertType(methPrmTypes.get(i)) + " " + methParams.get(i));
209 // Check if this is the last element (don't print a comma)
210 if (i != methParams.size() - 1) {
219 System.out.println("IoTStubCompiler: Generated interface " + newIntface + ".hpp...");
225 * generateJavaStubClasses() generate stubs based on the methods list in Java
227 public void generateJavaStubClasses() throws IOException {
229 // Create a new directory
230 createDirectory(dir);
231 for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
233 // Open a new file to write into
234 String newIntface = intMeth.getKey();
235 String newStubClass = newIntface + "_Stub";
236 FileWriter fw = new FileWriter(dir + "/" + newStubClass + ".java");
237 pw = new PrintWriter(new BufferedWriter(fw));
238 // Write interface header
240 println("public class " + newStubClass + " implements " + newIntface + " {");
243 for (String method : intMeth.getValue()) {
245 List<String> methParams = intDecl.getMethodParams(method);
246 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
247 print("public " + intDecl.getMethodType(method) + " " +
249 for (int i = 0; i < methParams.size(); i++) {
250 print(methPrmTypes.get(i) + " " + methParams.get(i));
251 // Check if this is the last element (don't print a comma)
252 if (i != methParams.size() - 1) {
257 // Check if this is not "void"
258 if (!intDecl.getMethodType(method).equals("void")) {
259 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
260 println("return " + retStmt + ";");
267 System.out.println("IoTStubCompiler: Generated stub class " + newStubClass + ".java...");
273 * generateCPlusStubClasses() generate stubs based on the methods list in C++
275 public void generateCPlusStubClasses() throws IOException {
277 // Create a new directory
278 createDirectory(dir);
279 for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
281 // Open a new file to write into
282 String newIntface = intMeth.getKey();
283 String newStubClass = newIntface + "_Stub";
284 FileWriter fw = new FileWriter(dir + "/" + newStubClass + ".hpp");
285 pw = new PrintWriter(new BufferedWriter(fw));
286 // Write file headers
287 println("#include<iostream>");
288 println("#include \"" + newIntface + ".hpp\""); println("");
289 println("using namespace std;"); println("");
290 println("class " + newStubClass + " : public " + newIntface);
292 println("public:"); println("");
293 // Add default constructor and destructor
294 println(newStubClass + "() { }"); println("");
295 println("~" + newStubClass + "() { }"); println("");
297 for (String method : intMeth.getValue()) {
299 List<String> methParams = intDecl.getMethodParams(method);
300 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
301 print(convertType(intDecl.getMethodType(method)) + " " +
303 for (int i = 0; i < methParams.size(); i++) {
304 print(convertType(methPrmTypes.get(i)) + " " + methParams.get(i));
305 // Check if this is the last element (don't print a comma)
306 if (i != methParams.size() - 1) {
311 // Check if this is not "void"
312 if (!intDecl.getMethodType(method).equals("void")) {
313 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
314 if (retStmt.equals("null")) { // null = NULL in C++
317 println("return " + retStmt + ";");
319 println("}"); println("");
321 print("}"); println(";");
323 System.out.println("IoTStubCompiler: Generated stub class " + newIntface + ".hpp...");
329 * generateReturnStmt() generate return statement based on methType
331 public String generateReturnStmt(String methType) {
333 // Generate dummy returns for now
334 if (methType.equals("short")||
335 methType.equals("int") ||
336 methType.equals("long") ||
337 methType.equals("float")||
338 methType.equals("double")) {
341 } else if ( methType.equals("String") ||
342 methType.equals("byte")) {
345 } else if ( methType.equals("char")) {
348 } else if ( methType.equals("boolean")) {
358 * setDirectory() set a new directory for stub files
360 public void setDirectory(String _dir) {
367 * printUsage() prints the usage of this compiler
369 public static void printUsage() {
371 System.out.println();
372 System.out.println("Sentinel stub compiler version 1.0");
373 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
374 System.out.println("All rights reserved.");
375 System.out.println("Usage:");
376 System.out.println("\tjava IoTStubCompiler --help\t\t\tDisplay this help texts");
377 System.out.println("\tjava IoTStubCompiler <policy-file>\t\tGenerate both Java and C++ stub files");
378 System.out.println("\tjava IoTStubCompiler <policy-file> [options]");
379 System.out.println("Options:");
380 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
381 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
382 System.out.println();
386 /**================================================
387 * Helper functions to write stub codes into files
388 **================================================
390 boolean newline=true;
393 private void print(String str) {
398 for(int i=0; i<tab; i++)
407 * This function converts Java to C++ type for compilation
409 private String convertType(String jType) {
411 // Generate dummy returns for now
412 if (jType.equals("short")||
413 jType.equals("int") ||
414 jType.equals("long") ||
415 jType.equals("char") ||
416 jType.equals("float")||
417 jType.equals("double")) {
420 } else if ( jType.equals("String")) {
423 } else if ( jType.equals("byte")) {
426 } else if ( jType.equals("boolean")) {
435 private void println(String str) {
440 for(int i=0; i<tab; i++)
449 private void updatetabbing(String str) {
450 tablevel+=count(str,'{')-count(str,'}');
454 private int count(String str, char key) {
455 char[] array = str.toCharArray();
457 for(int i=0; i<array.length; i++) {
465 private void createDirectory(String dirName) {
467 File file = new File(dirName);
468 if (!file.exists()) {
470 System.out.println("IoTStubCompiler: Directory " + dirName + "has been created!");
472 System.out.println("IoTStubCompiler: Failed to create directory " + dirName + "!");
475 System.out.println("IoTStubCompiler: Directory " + dirName + " exists...");
480 public static void main(String[] args) throws Exception {
483 if (args.length != 0) {
485 if (args[0].equals("--help")) {
486 IoTStubCompiler.printUsage();
488 // Initialize the symbol factory
489 ComplexSymbolFactory csf = new ComplexSymbolFactory();
490 // Create a buffering scanner wrapper
491 ScannerBuffer lexer =
492 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(args[0])),csf));
494 Parser p = new Parser(lexer,csf);
495 ParseNode pn = (ParseNode) p.parse().value;
496 // Handle parse-tree and process it
497 String intFace = ParseTreeHandler.getOrigIntface(pn);
498 //System.out.println("IoTStubCompiler: Original interface: " + intFace);
499 IoTStubCompiler stubComp = new IoTStubCompiler(intFace, pn);
500 // Generate all policy files if just policy file is provided
501 stubComp.parsePolicyFile();
502 stubComp.getMethodsForIntface();
503 if (args.length == 1) {
504 stubComp.generateJavaInterfaces();
505 stubComp.generateJavaStubClasses();
506 stubComp.generateCPlusInterfaces();
507 stubComp.generateCPlusStubClasses();
509 // Check other options
511 while(i < args.length) {
512 // Check whether <directory> is provided
513 if ((i + 1) < args.length) {
514 stubComp.setDirectory(args[i+1]);
516 throw new Error("IoTStubCompiler: ERROR - please provide <directory> after option: " + args[i]);
517 if (args[i].equals("-java")) {
518 stubComp.generateJavaInterfaces();
519 stubComp.generateJavaStubClasses();
520 } else if (args[i].equals("-cplus")) {
521 stubComp.generateCPlusInterfaces();
522 stubComp.generateCPlusStubClasses();
524 throw new Error("IoTStubCompiler: ERROR - unrecognized command line option: " + args[i]);
531 // Need at least the policy file name
532 IoTStubCompiler.printUsage();
533 throw new Error("IoTStubCompiler: At least one argument (policy file) has to be provided!");