KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > carol > cmi > compiler > Compiler


1 /*
2  * Copyright (C) 2002-2003, Simon Nieuviarts
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA
18  */

19 package org.objectweb.carol.cmi.compiler;
20
21 import java.io.File JavaDoc;
22 import java.io.FileWriter JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLClassLoader JavaDoc;
28 import java.rmi.Remote JavaDoc;
29 import java.rmi.RemoteException JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.Comparator JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38 import java.util.TreeSet JavaDoc;
39 import java.util.Vector JavaDoc;
40
41 /**
42  * @author nieuviar
43  *
44  */

45 public class Compiler {
46     private boolean keep = false;
47     private boolean noc = false;
48     private String JavaDoc compiler = "javac";
49     private String JavaDoc classPath = null;
50     private String JavaDoc genConf = null;
51     private ArrayList JavaDoc conf = new ArrayList JavaDoc();
52     private ArrayList JavaDoc classes = new ArrayList JavaDoc();
53     private String JavaDoc srcDir = null;
54     private String JavaDoc destDir = ".";
55     private boolean invokeCmd = false;
56     private ClassLoader JavaDoc classLoader = Thread.currentThread().getContextClassLoader();
57
58     public void configure(String JavaDoc[] args) throws CompilerException {
59         int i = 0;
60         while (i < args.length) {
61             String JavaDoc arg = args[i++];
62             if (arg.equals("-keep") || arg.equals("-keepgenerated")) {
63                 keep = true;
64             } else if (arg.equals("-noc")) {
65                 noc = true;
66             } else if (arg.equals("-invokecmd")) {
67                 invokeCmd = true;
68             } else if (arg.equals("-c")) {
69                 if (i == args.length) {
70                     throw new CompilerException("-c : missing argument");
71                 }
72                 compiler = args[i++];
73             } else if (arg.equals("-classpath")) {
74                 if (i == args.length) {
75                     throw new CompilerException("-classpath : missing argument");
76                 }
77                 classPath = args[i++];
78             } else if (arg.equals("-genconf")) {
79                 if (i == args.length) {
80                     throw new CompilerException("-genconf : missing argument");
81                 }
82                 genConf = args[i++];
83             } else if (arg.equals("-conf")) {
84                 if (i == args.length) {
85                     throw new CompilerException("-conf : missing argument");
86                 }
87                 conf.add(args[i++]);
88             } else if (arg.equals("-d")) {
89                 if (i == args.length) {
90                     throw new CompilerException("-d : missing argument");
91                 }
92                 destDir = args[i++];
93             } else if (arg.equals("-s")) {
94                 if (i == args.length) {
95                     throw new CompilerException("-s : missing argument");
96                 }
97                 srcDir = args[i++];
98             } else if (arg.startsWith("-")) {
99                 throw new CompilerException(arg + ": unknown option");
100             } else {
101                 classes.add(arg);
102             }
103         }
104         if (srcDir == null) {
105             srcDir = destDir;
106         }
107         if (noc) {
108             keep = true;
109         }
110         if (classPath != null) {
111             classLoader = buildClassLoader(classPath);
112         }
113     }
114
115     public void run() throws CompilerException {
116         if (genConf != null) {
117             if (conf.size() != 0) {
118                 System.err.println("options -conf and -genconf are not compatible");
119                 System.exit(1);
120             }
121             generateClusterConfExample();
122         } else {
123             ArrayList JavaDoc generatedFiles = new ArrayList JavaDoc();
124             Conf cconf = new Conf(classLoader, classes);
125             Iterator JavaDoc i = conf.iterator();
126             while (i.hasNext()) {
127                 cconf.loadConfig((String JavaDoc) i.next());
128             }
129             i = classes.iterator();
130             while (i.hasNext()) {
131                 String JavaDoc className = (String JavaDoc) i.next();
132                 if (className == null || className == "") {
133                     throw new CompilerException("Empty class name to compile");
134                 }
135                 TemplateCompiler tc =
136                     new TemplateCompiler(this, cconf.getClassConf(className));
137                 generatedFiles.add(tc.genConfig());
138                 generatedFiles.add(tc.genStub());
139             }
140
141             compileAndRemove(generatedFiles);
142
143         }
144     }
145
146     public void compileAndRemove(String JavaDoc fileName) throws CompilerException {
147         compileAndRemove(Collections.singleton(fileName));
148     }
149
150     public void compileAndRemove(Collection JavaDoc fileNames)
151         throws CompilerException {
152         try {
153             if (!noc) {
154                 Utils.compileFiles(this, fileNames);
155             }
156         } finally {
157             if (!keep) {
158                 Utils.deleteFiles(fileNames);
159             }
160         }
161     }
162
163     private void generateClusterConfExample()
164         throws CompilerException {
165         try {
166             FileWriter JavaDoc f = new FileWriter JavaDoc(genConf);
167             f.write("<!DOCTYPE cluster-config PUBLIC\n");
168             f.write("\t\"\"\n");
169             f.write("\t\"cluster-config-0.2.dtd\">\n\n");
170             f.write("<cluster-config>\n\n");
171             Iterator JavaDoc i = classes.iterator();
172             while (i.hasNext()) {
173                 String JavaDoc className = (String JavaDoc) i.next();
174                 Class JavaDoc cl;
175                 try {
176                     cl = loadClass(className);
177                 } catch (ClassNotFoundException JavaDoc e1) {
178                     throw new CompilerException("class not found " + className, e1);
179                 }
180                 f.write("<class>\n\t<name>" + className + "</name>\n\t<random>\n");
181                 Method JavaDoc[] remMths = getRemoteMethods(cl);
182                 for (int j = 0; j < remMths.length; j++) {
183                     f.write("\t<method>\n\t\t<signature>");
184                     f.write(new MethodProto(remMths[j]).toString());
185                     f.write("</signature>\n\t</method>\n");
186                 }
187                 f.write("\t</random>\n</class>\n\n");
188             }
189             f.write("</cluster-config>\n");
190             f.close();
191         } catch (IOException JavaDoc e) {
192             throw new CompilerException(genConf, e);
193         }
194     }
195
196     public Class JavaDoc loadClass(String JavaDoc className) throws ClassNotFoundException JavaDoc {
197         return classLoader.loadClass(className);
198     }
199
200     public static boolean isRemoteItf(Class JavaDoc cl) {
201         // The interface must extend java.rmi.Remote
202
if (!cl.isInterface() || !Remote JavaDoc.class.isAssignableFrom(cl)) {
203             return false;
204         }
205
206         // Each method of this interface must throw java.rmi.RemoteException
207
Method JavaDoc[] m = cl.getMethods();
208         for (int i=0; i<m.length; i++) {
209             Class JavaDoc[] ex = m[i].getExceptionTypes();
210             int j = 0;
211             while ((j < ex.length) && !RemoteException JavaDoc.class.isAssignableFrom(ex[j])) {
212                 j++;
213             }
214             if (j == ex.length) {
215                 return false;
216             }
217         }
218         return true;
219     }
220
221     public static Set JavaDoc getRemoteItfs(Class JavaDoc cl) {
222         Set JavaDoc remItfs = new HashSet JavaDoc();
223         while (cl != null) {
224             Class JavaDoc[] itfs = cl.getInterfaces();
225             if (isRemoteItf(cl)) {
226                 remItfs.add(cl);
227             }
228             for (int i=0; i<itfs.length; i++) {
229                 Class JavaDoc itf = itfs[i];
230                 if (isRemoteItf(itf)) {
231                     remItfs.add(itf);
232                 }
233             }
234             cl = cl.getSuperclass();
235         }
236         return remItfs;
237     }
238
239     public static class MethodComparator implements Comparator JavaDoc {
240         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
241             Method JavaDoc m1 = (Method JavaDoc)o1;
242             Method JavaDoc m2 = (Method JavaDoc)o2;
243             int r = m1.getName().compareTo(m2.getName());
244             if (r != 0) return r;
245             Class JavaDoc[] p1 = m1.getParameterTypes();
246             Class JavaDoc[] p2 = m2.getParameterTypes();
247             int i = 0;
248             while ((i < p1.length) && (i < p2.length)) {
249                 r = MethodProto.getName(p1[i]).compareTo(MethodProto.getName(p2[i]));
250                 if (r != 0) return r;
251                 i++;
252             }
253             if (i == p1.length) {
254                 if (i == p2.length) {
255                     return 0;
256                 }
257                 return -1;
258             }
259             return 1;
260         }
261     }
262
263     private static MethodComparator methodComparator = new MethodComparator();
264
265     // Return remote methods, sorted lexigraphically
266
public static Method JavaDoc[] getRemoteMethods(Class JavaDoc cl) {
267         TreeSet JavaDoc remMethods = new TreeSet JavaDoc(methodComparator);
268         // Get the methods of the remote interfaces
269
Set JavaDoc itfs = getRemoteItfs(cl);
270         TreeSet JavaDoc itfMethods = new TreeSet JavaDoc(methodComparator);
271         Iterator JavaDoc it = itfs.iterator();
272         while (it.hasNext()) {
273             Class JavaDoc itf = (Class JavaDoc) it.next();
274             Method JavaDoc[] m = itf.getMethods();
275             for (int i=0; i<m.length; i++) {
276                 itfMethods.add(m[i]);
277             }
278         }
279
280         TreeSet JavaDoc clMethods = new TreeSet JavaDoc(methodComparator);
281         Method JavaDoc[] methods = cl.getMethods();
282         for (int i=0; i<methods.length; i++) {
283             clMethods.add(methods[i]);
284         }
285
286         Iterator JavaDoc i1 = clMethods.iterator();
287         Iterator JavaDoc i2 = itfMethods.iterator();
288         if (i1.hasNext() && i2.hasNext()) {
289             Method JavaDoc m1 = (Method JavaDoc) i1.next();
290             Method JavaDoc m2 = (Method JavaDoc) i2.next();
291             do {
292                 int d = methodComparator.compare(m1, m2);
293                 if (d > 0) {
294                     m2 = (i2.hasNext()) ? (Method JavaDoc)i2.next() : null;
295                 } else if (d < 0) {
296                     m1 = (i1.hasNext()) ? (Method JavaDoc)i1.next() : null;
297                 } else {
298                     // Give the Method object of the interface
299
remMethods.add(m2);
300                     m1 = (i1.hasNext()) ? (Method JavaDoc)i1.next() : null;
301                     m2 = (i2.hasNext()) ? (Method JavaDoc)i2.next() : null;
302                 }
303             } while ((m1 != null) && (m2 != null));
304         }
305
306         int i = remMethods.size();
307         Method JavaDoc[] m = new Method JavaDoc[i];
308         it = remMethods.iterator();
309         i = 0;
310         while (it.hasNext()) {
311             m[i++] = (Method JavaDoc) it.next();
312         }
313         return m;
314     }
315
316     public static ClassLoader JavaDoc buildClassLoader(String JavaDoc classPath) {
317         String JavaDoc classpath = classPath + System.getProperty("path.separator", "") + System.getProperty("java.class.path", "");
318         Vector JavaDoc nurls = new Vector JavaDoc();
319         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(classpath, System.getProperty("path.separator", ""));
320         while (st.hasMoreTokens()) {
321             String JavaDoc url = st.nextToken();
322             if (!url.equals("")) {
323                 try {
324                     URL JavaDoc u = (new File JavaDoc(url)).toURL();
325                     nurls.addElement(u);
326                 } catch (MalformedURLException JavaDoc e) {
327                     // Do not add the URL
328
}
329             }
330         }
331         if (nurls.size() == 0) {
332             return Thread.currentThread().getContextClassLoader();
333         }
334         URL JavaDoc urls[] = new URL JavaDoc[nurls.size()];
335         nurls.copyInto(urls);
336         return new URLClassLoader JavaDoc(urls, null);
337     }
338
339     public static void usage() {
340         System.out.println(
341             "Usage: java "
342                 + MethodProto.getName(Compiler JavaDoc.class)
343                 + " [options] [class names]");
344         System.out.println();
345         System.out.println(
346             "Options:\n"
347                 + " -keep do not delete generated source files\n"
348                 + " -keepgenerated same as -keep\n"
349                 + " -noc do not compile generated source files (implies -keep)\n"
350                 + " -c <java compiler> compile generated source files with this java compiler\n"
351                 + " (defaults to javac)\n"
352                 + " -classpath <path> extra classpath passed to -c compiler\n"
353                 + " -d <directory> root directory for generated class files "
354                 + " (defaults to current directory)\n"
355                 + " -s <directory> root directory for generated source files\n"
356                 + " (defaults to -d directory)\n"
357                 + " -conf <xml-file> specify the XML configuration file to use\n"
358                 + " -genconf <xml-file> generate an XML configuration file example\n");
359     }
360
361     public static void generate(String JavaDoc[] args) throws CompilerException {
362         Compiler JavaDoc cc = new Compiler JavaDoc();
363         cc.configure(args);
364         cc.run();
365     }
366
367     public static void main(String JavaDoc[] args) {
368         if (args.length == 0) {
369             usage();
370             return;
371         }
372         try {
373             generate(args);
374         } catch (Exception JavaDoc e) {
375             e.printStackTrace();
376             System.exit(1);
377         }
378     }
379
380     public String JavaDoc getSrcDir() {
381         return srcDir;
382     }
383
384     public boolean isCompile() {
385         return !noc;
386     }
387
388     public String JavaDoc getCompiler() {
389         return compiler;
390     }
391
392     public String JavaDoc getDestDir() {
393         return destDir;
394     }
395
396     public String JavaDoc getClassPath() {
397         return classPath;
398     }
399     
400     public boolean isInvokeCmd() {
401         return invokeCmd;
402     }
403 }
404
Popular Tags