Adding last version of iotruntime and iotinstaller; preparing to extend IoTMaster...
[iot2.git] / iotjava / iotruntime / stub / IoTStubCodeGenerator.java
diff --git a/iotjava/iotruntime/stub/IoTStubCodeGenerator.java b/iotjava/iotruntime/stub/IoTStubCodeGenerator.java
new file mode 100644 (file)
index 0000000..e8f70d4
--- /dev/null
@@ -0,0 +1,242 @@
+package iotruntime.stub;
+
+// Java libraries
+import java.io.BufferedWriter;
+import java.io.PrintWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+
+import java.lang.Class;
+import java.lang.reflect.*;
+
+
+/** IoTStubGenerator class that takes an interface,
+ *  instrument it using Java Reflection, and generate
+ *  static code that uses IoTRemoteCall as a stub object
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0
+ * @since       2016-04-14
+ */
+public class IoTStubCodeGenerator {
+
+       /**
+        * IoTStubCodeGenerator properties
+        */
+       PrintWriter pw;
+       String strInterfaceName;
+       String strNewClassName;
+       String strCallbackIntName;
+
+       /**
+        * Constructor
+        */
+       public IoTStubCodeGenerator(String[] strArgs) throws Exception {
+
+               this.strInterfaceName = strArgs[0];
+               if (strArgs.length == 1) {
+               // If callback interface is not specified
+                       this.strCallbackIntName = "Object";
+               } else {
+                       this.strCallbackIntName = strArgs[1];
+               }
+               strNewClassName = strInterfaceName + "Implementation";
+               FileWriter fw = new FileWriter(strNewClassName + ".java");
+               pw = new PrintWriter(new BufferedWriter(fw));
+       }
+
+       /**
+        * Instrument interface class
+        */
+       public void instrumentInterfaceClass() {
+
+               // Write the imports
+               generateImports();
+               // Write the class header
+               println("public final class " + strNewClassName + 
+                               " extends IoTJSONStub " +
+                               " implements " + strInterfaceName + " {");
+               println("");
+               generateFields();
+               println("");
+               generateConstructor();
+               println("");
+
+               try {
+                       Class<?>cls = Class.forName(strInterfaceName);
+                       for (Method mtd : cls.getDeclaredMethods()) {
+                               generateMethod(mtd);
+                               println("");
+                       }
+               } catch (ClassNotFoundException ex) {
+                       ex.printStackTrace();
+               }
+               generateMethodCallback();
+
+               //Close class
+               println("}");
+               pw.close();
+       }
+
+       /**
+        * Generate import statements
+        */
+       private void generateImports() {
+               // Write the class properties
+               println("import iotruntime.stub.IoTRemoteCall;");
+               println("import iotruntime.stub.IoTJSONStub;");
+               println("import iotruntime.slave.IoTDeviceAddress;");
+               println("");
+       }
+
+       /**
+        * Generate fields
+        */
+       private void generateFields() {
+               // Write the class properties
+               println("private IoTRemoteCall iotremotecall;");
+               println("private " + strCallbackIntName + " callbackObject;");
+       }
+
+       /**
+        * Generate constructor
+        */
+       private void generateConstructor() {
+               // Write the constructor
+               println("public " + strNewClassName + 
+                       "(IoTDeviceAddress _iotDevAdd) {");
+               println("super(_iotDevAdd);");
+               println("this.iotremotecall = new IoTRemoteCall();");
+               print("String[] arrMethodName = { \"");
+               // Get the interface class
+               try {
+                       Class<?>cls = Class.forName(strInterfaceName);
+                       Method[] method = cls.getDeclaredMethods();
+                       for (Method mtd: method) {
+                               print(mtd.getName());
+                               // Check if this is the last element
+                               if (!mtd.equals(method[method.length-1])) {
+                                       print("\", \"");
+                               }
+                       }
+                       println("\" };");
+                       println("this.iotremotecall.startHttpServer(arrMethodName, " +
+                                       "iotDevAddress.getDestinationPortNumber());");
+               } catch (ClassNotFoundException ex) {
+                       ex.printStackTrace();
+               }
+               println("}");
+       }
+
+       /**
+        * Generate method body
+        */
+       private void generateMethod(Method mtd) {
+
+               Class<?> clsReturn = mtd.getReturnType();
+               // Write the method declaration
+               print("public " + clsReturn.getSimpleName() + " " + mtd.getName() + "(");
+               Parameter[] params = mtd.getParameters();
+               // Write the method params
+               for (Parameter param:params) {
+                       print(param.getType().getSimpleName() + " " + param.getName());
+                       // Check if this is the last element
+                       if (!param.equals(params[params.length-1])) {
+                               print(", ");
+                       }
+               }
+               println(") {");
+               // Write the method body
+               // Handle return value
+               println("String strMethodName = \"" + mtd.getName() + "\";");
+               // Handle inputs
+    print("Object[] arrInpValue = { ");
+    for (Parameter param:params) {
+      print(param.getName());
+      // Check if this is the last element
+      if (!param.equals(params[params.length-1])) {
+        print(", ");
+      }
+    }
+    println(" };");
+    print("String[] arrInpType = { \"");
+    for (Parameter param:params) {
+      print(param.getType().getSimpleName());
+      // Check if this is the last element
+      if (!param.equals(params[params.length-1])) {
+        print("\", \"");
+      }
+    }          
+    println("\" };");
+    println("Object _retval=iotremotecall.callMethod(strMethodName, iotDevAddress.getHostAddress(), iotDevAddress.getDestinationPortNumber(), arrInpValue, arrInpType, \""+ clsReturn.getSimpleName()+ "\");");
+    if (!clsReturn.equals(Void.class)) {
+      println("return ("+clsReturn.getSimpleName()+") _retval;");
+    }
+    
+               println("}");
+       }
+
+       private void generateMethodCallback() {
+
+               // Write the method
+               println("public void registerCallback(Object objCallback) {");
+               println("this.callbackObject = (" + strCallbackIntName + ") objCallback;");
+               println("}");
+       }
+
+
+       boolean newline=true;
+       int tablevel=0;
+
+       private void print(String str) {
+               if (newline) {
+                       int tab=tablevel;
+                       if (str.equals("}"))
+                               tab--;
+                       for(int i=0; i<tab; i++)
+                               pw.print("\t");
+               }
+               pw.print(str);
+               updatetabbing(str);
+               newline=false;
+       }
+
+       private void println(String str) {
+               if (newline) {
+                       int tab = tablevel;
+                       if (str.equals("}"))
+                               tab--;
+                       for(int i=0; i<tab; i++)
+                               pw.print("\t");
+               }
+               pw.println(str);
+               updatetabbing(str);
+               newline = true;
+       }
+
+       private void updatetabbing(String str) {
+               tablevel+=count(str,'{')-count(str,'}');
+       }
+
+       private int count(String str, char key) {
+               char[] array = str.toCharArray();
+               int count = 0;
+               for(int i=0; i<array.length; i++) {
+                       if (array[i] == key)
+                               count++;
+               }
+               return count;
+       }
+
+       public static void main(String[] args) throws Exception {
+               // args[0] = normal interface name
+               // args[1] = callback interface name
+               IoTStubCodeGenerator stub = new IoTStubCodeGenerator(args);
+               stub.instrumentInterfaceClass();
+       }
+}