2 import java.io.*;
3 import java.util.HashMap;
4 import java.util.ArrayList;
5 import java.util.Collections;
8 /**
9 * This is not an actual java binding class. Rather, it is
10 * a simple tool for generating C++ native method stubs from classfiles
11 */
12 public class DomStub
13 {
15 class MethodEntry
16 {
17 ArrayList<String> parms;
18 String name;
19 String type;
21 public void addParam(String type)
22 {
23 parms.add(type);
24 }
26 public MethodEntry(String methodName, String type)
27 {
28 this.name = methodName;
29 this.type = type;
30 parms = new ArrayList<String>();
31 }
32 }
35 class ClassEntry
36 {
37 ArrayList<MethodEntry> methods;
38 String name;
40 public void addMethod(MethodEntry method)
41 {
42 methods.add(method);
43 }
45 public ClassEntry(String className)
46 {
47 this.name = className;
48 methods = new ArrayList<MethodEntry>();
49 }
50 }
53 HashMap<String, ClassEntry> classes;
56 BufferedWriter out;
58 void err(String msg)
59 {
60 System.out.println("DomStub err:" + msg);
61 }
63 void trace(String msg)
64 {
65 System.out.println("DomStub:" + msg);
66 }
68 void po(String msg)
69 {
70 try
71 {
72 out.write(msg);
73 }
74 catch (IOException e)
75 {
76 }
77 }
80 //########################################################################
81 //# G E N E R A T E
82 //########################################################################
84 void dumpClasses()
85 {
86 for (ClassEntry ce : classes.values())
87 {
88 trace("########################");
89 trace("Class " + ce.name);
90 for (MethodEntry me : ce.methods)
91 {
92 trace(" " + me.type + " " + me.name);
93 for (String parm : me.parms)
94 {
95 trace(" " + parm);
96 }
97 }
98 }
99 }
102 void generateMethod(MethodEntry me)
103 {
104 po("/**\n");
105 po(" * Method : " + me.name + "\n");
106 po(" */\n");
107 for (String parm : me.parms)
108 {
109 po(" " + parm + "\n");
110 }
112 }
114 void generateClass(ClassEntry ce)
115 {
116 po("//################################################################\n");
117 po("//## " + ce.name + "\n");
118 po("//################################################################\n");
120 for (MethodEntry me : ce.methods)
121 generateMethod(me);
123 }
126 void generate()
127 {
128 ArrayList<String> classNames = new ArrayList<String>(classes.keySet());
129 Collections.sort(classNames);
130 for (String key : classNames)
131 {
132 ClassEntry ce = classes.get(key);
133 generateClass(ce);
134 }
135 }
137 //########################################################################
138 //# P A R S E
139 //########################################################################
140 boolean parseEntry(String className, String methodName, String signature)
141 {
142 //trace("Decl :" + methodDecl);
143 //trace("params:" + params);
144 //#################################
145 //# Parse class and method lines
146 //#################################
147 String s = className.substring(14);
148 className = s.replace('_', '/');
149 methodName = methodName.substring(14);
150 signature = signature.substring(14);
151 //trace("className : " + className);
152 //trace("methodName : " + methodName);
154 int pos = signature.indexOf('(');
155 if (pos<0)
156 {
157 err("no opening ( for signature");
158 return false;
159 }
160 pos++;
161 int p2 = signature.indexOf(')', pos);
162 if (p2<0)
163 {
164 err("no closing ) for signature");
165 return false;
166 }
167 String parms = signature.substring(pos, p2);
168 String type = signature.substring(p2+1);
169 //#################################
170 //# create method entry. add to new or existing class
171 //#################################
172 MethodEntry method = new MethodEntry(methodName, type);
174 ClassEntry clazz = classes.get(className);
175 if (clazz == null)
176 {
177 clazz = new ClassEntry(className);
178 classes.put(className, clazz);
179 }
180 clazz.addMethod(method);
182 //#################################
183 //# Parse signature line
184 //#################################
186 pos = 0;
187 int len = parms.length();
188 while (pos<len)
189 {
190 String typ = "";
191 char ch = parms.charAt(pos);
192 if (ch == '[')
193 {
194 pos++;
195 ch = parms.charAt(pos);
196 typ += ch;
197 }
198 if (ch == 'L')
199 {
200 pos++;
201 typ += ch;
202 while (pos<len)
203 {
204 ch = parms.charAt(pos);
205 if (ch == ';')
206 break;
207 typ += ch;
208 pos++;
209 }
210 }
211 else
212 typ += ch;
213 method.addParam(typ);
214 //trace("param:" + typ);
215 pos++;
216 }
217 return true;
218 }
221 public boolean parseFile(String fname)
222 {
223 boolean ret = true;
224 try
225 {
226 BufferedReader in = new BufferedReader(new FileReader(fname));
227 while (true)
228 {
229 String s1 = in.readLine();
230 if (s1 == null)
231 break;
232 if (!s1.startsWith(" * Class: "))
233 continue;
234 String s2 = in.readLine();
235 if (!s2.startsWith(" * Method: "))
236 continue;
237 String s3 = in.readLine();
238 if (!s3.startsWith(" * Signature: "))
239 continue;
240 if (!parseEntry(s1, s2, s3))
241 {
242 ret = false;
243 break;
244 }
245 }
246 in.close();
247 }
248 catch (IOException e)
249 {
250 err("processFile:" + e);
251 ret = false;
252 }
253 return ret;
254 }
257 public boolean processFile(String fname)
258 {
259 try
260 {
261 out = new BufferedWriter(new FileWriter("out.txt"));
262 }
263 catch (IOException e)
264 {
265 err("processFile: " + e);
266 return false;
267 }
268 if (!parseFile(fname))
269 return false;
270 //dumpClasses();
271 generate();
272 try
273 {
274 out.close();
275 }
276 catch (IOException e)
277 {
278 err("processFile: " + e);
279 return false;
280 }
281 return true;
282 }
285 public DomStub()
286 {
287 classes = new HashMap<String, ClassEntry>();
288 }
292 public static void main(String argv[])
293 {
294 DomStub st = new DomStub();
295 boolean ret = st.processFile("out.h");
296 }
299 }