Adding last version of iotruntime and iotinstaller; preparing to extend IoTMaster...
[iot2.git] / iotjava / iotruntime / stub / IoTStubCodeGenerator.java
1 package iotruntime.stub;
2
3 // Java libraries
4 import java.io.BufferedWriter;
5 import java.io.PrintWriter;
6 import java.io.FileWriter;
7 import java.io.IOException;
8
9 import java.net.HttpURLConnection;
10 import java.net.MalformedURLException;
11 import java.net.ProtocolException;
12 import java.net.URL;
13
14 import java.lang.Class;
15 import java.lang.reflect.*;
16
17
18 /** IoTStubGenerator class that takes an interface,
19  *  instrument it using Java Reflection, and generate
20  *  static code that uses IoTRemoteCall as a stub object
21  *
22  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
23  * @version     1.0
24  * @since       2016-04-14
25  */
26 public class IoTStubCodeGenerator {
27
28         /**
29          * IoTStubCodeGenerator properties
30          */
31         PrintWriter pw;
32         String strInterfaceName;
33         String strNewClassName;
34         String strCallbackIntName;
35
36         /**
37          * Constructor
38          */
39         public IoTStubCodeGenerator(String[] strArgs) throws Exception {
40
41                 this.strInterfaceName = strArgs[0];
42                 if (strArgs.length == 1) {
43                 // If callback interface is not specified
44                         this.strCallbackIntName = "Object";
45                 } else {
46                         this.strCallbackIntName = strArgs[1];
47                 }
48                 strNewClassName = strInterfaceName + "Implementation";
49                 FileWriter fw = new FileWriter(strNewClassName + ".java");
50                 pw = new PrintWriter(new BufferedWriter(fw));
51         }
52
53         /**
54          * Instrument interface class
55          */
56         public void instrumentInterfaceClass() {
57
58                 // Write the imports
59                 generateImports();
60                 // Write the class header
61                 println("public final class " + strNewClassName + 
62                                 " extends IoTJSONStub " +
63                                 " implements " + strInterfaceName + " {");
64                 println("");
65                 generateFields();
66                 println("");
67                 generateConstructor();
68                 println("");
69
70                 try {
71                         Class<?>cls = Class.forName(strInterfaceName);
72                         for (Method mtd : cls.getDeclaredMethods()) {
73                                 generateMethod(mtd);
74                                 println("");
75                         }
76                 } catch (ClassNotFoundException ex) {
77                         ex.printStackTrace();
78                 }
79                 generateMethodCallback();
80
81                 //Close class
82                 println("}");
83                 pw.close();
84         }
85
86         /**
87          * Generate import statements
88          */
89         private void generateImports() {
90                 // Write the class properties
91                 println("import iotruntime.stub.IoTRemoteCall;");
92                 println("import iotruntime.stub.IoTJSONStub;");
93                 println("import iotruntime.slave.IoTDeviceAddress;");
94                 println("");
95         }
96
97         /**
98          * Generate fields
99          */
100         private void generateFields() {
101                 // Write the class properties
102                 println("private IoTRemoteCall iotremotecall;");
103                 println("private " + strCallbackIntName + " callbackObject;");
104         }
105
106         /**
107          * Generate constructor
108          */
109         private void generateConstructor() {
110                 // Write the constructor
111                 println("public " + strNewClassName + 
112                         "(IoTDeviceAddress _iotDevAdd) {");
113                 println("super(_iotDevAdd);");
114                 println("this.iotremotecall = new IoTRemoteCall();");
115                 print("String[] arrMethodName = { \"");
116                 // Get the interface class
117                 try {
118                         Class<?>cls = Class.forName(strInterfaceName);
119                         Method[] method = cls.getDeclaredMethods();
120                         for (Method mtd: method) {
121                                 print(mtd.getName());
122                                 // Check if this is the last element
123                                 if (!mtd.equals(method[method.length-1])) {
124                                         print("\", \"");
125                                 }
126                         }
127                         println("\" };");
128                         println("this.iotremotecall.startHttpServer(arrMethodName, " +
129                                         "iotDevAddress.getDestinationPortNumber());");
130                 } catch (ClassNotFoundException ex) {
131                         ex.printStackTrace();
132                 }
133                 println("}");
134         }
135
136         /**
137          * Generate method body
138          */
139         private void generateMethod(Method mtd) {
140
141                 Class<?> clsReturn = mtd.getReturnType();
142                 // Write the method declaration
143                 print("public " + clsReturn.getSimpleName() + " " + mtd.getName() + "(");
144                 Parameter[] params = mtd.getParameters();
145                 // Write the method params
146                 for (Parameter param:params) {
147                         print(param.getType().getSimpleName() + " " + param.getName());
148                         // Check if this is the last element
149                         if (!param.equals(params[params.length-1])) {
150                                 print(", ");
151                         }
152                 }
153                 println(") {");
154                 // Write the method body
155                 // Handle return value
156                 println("String strMethodName = \"" + mtd.getName() + "\";");
157                 // Handle inputs
158     print("Object[] arrInpValue = { ");
159     for (Parameter param:params) {
160       print(param.getName());
161       // Check if this is the last element
162       if (!param.equals(params[params.length-1])) {
163         print(", ");
164       }
165     }
166     println(" };");
167     print("String[] arrInpType = { \"");
168     for (Parameter param:params) {
169       print(param.getType().getSimpleName());
170       // Check if this is the last element
171       if (!param.equals(params[params.length-1])) {
172         print("\", \"");
173       }
174     }           
175     println("\" };");
176     println("Object _retval=iotremotecall.callMethod(strMethodName, iotDevAddress.getHostAddress(), iotDevAddress.getDestinationPortNumber(), arrInpValue, arrInpType, \""+ clsReturn.getSimpleName()+ "\");");
177     if (!clsReturn.equals(Void.class)) {
178       println("return ("+clsReturn.getSimpleName()+") _retval;");
179     }
180     
181                 println("}");
182         }
183
184         private void generateMethodCallback() {
185
186                 // Write the method
187                 println("public void registerCallback(Object objCallback) {");
188                 println("this.callbackObject = (" + strCallbackIntName + ") objCallback;");
189                 println("}");
190         }
191
192
193         boolean newline=true;
194         int tablevel=0;
195
196         private void print(String str) {
197                 if (newline) {
198                         int tab=tablevel;
199                         if (str.equals("}"))
200                                 tab--;
201                         for(int i=0; i<tab; i++)
202                                 pw.print("\t");
203                 }
204                 pw.print(str);
205                 updatetabbing(str);
206                 newline=false;
207         }
208
209         private void println(String str) {
210                 if (newline) {
211                         int tab = tablevel;
212                         if (str.equals("}"))
213                                 tab--;
214                         for(int i=0; i<tab; i++)
215                                 pw.print("\t");
216                 }
217                 pw.println(str);
218                 updatetabbing(str);
219                 newline = true;
220         }
221
222         private void updatetabbing(String str) {
223                 tablevel+=count(str,'{')-count(str,'}');
224         }
225
226         private int count(String str, char key) {
227                 char[] array = str.toCharArray();
228                 int count = 0;
229                 for(int i=0; i<array.length; i++) {
230                         if (array[i] == key)
231                                 count++;
232                 }
233                 return count;
234         }
235
236         public static void main(String[] args) throws Exception {
237                 // args[0] = normal interface name
238                 // args[1] = callback interface name
239                 IoTStubCodeGenerator stub = new IoTStubCodeGenerator(args);
240                 stub.instrumentInterfaceClass();
241         }
242 }