1 19 package org.objectweb.carol.cmi.compiler; 20 21 import java.io.File ; 22 import java.io.FileWriter ; 23 import java.io.IOException ; 24 import java.lang.reflect.Method ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.net.URLClassLoader ; 28 import java.rmi.Remote ; 29 import java.rmi.RemoteException ; 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Collections ; 33 import java.util.Comparator ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.Set ; 37 import java.util.StringTokenizer ; 38 import java.util.TreeSet ; 39 import java.util.Vector ; 40 41 45 public class Compiler { 46 private boolean keep = false; 47 private boolean noc = false; 48 private String compiler = "javac"; 49 private String classPath = null; 50 private String genConf = null; 51 private ArrayList conf = new ArrayList (); 52 private ArrayList classes = new ArrayList (); 53 private String srcDir = null; 54 private String destDir = "."; 55 private boolean invokeCmd = false; 56 private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 57 58 public void configure(String [] args) throws CompilerException { 59 int i = 0; 60 while (i < args.length) { 61 String 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 generatedFiles = new ArrayList (); 124 Conf cconf = new Conf(classLoader, classes); 125 Iterator i = conf.iterator(); 126 while (i.hasNext()) { 127 cconf.loadConfig((String ) i.next()); 128 } 129 i = classes.iterator(); 130 while (i.hasNext()) { 131 String className = (String ) 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 fileName) throws CompilerException { 147 compileAndRemove(Collections.singleton(fileName)); 148 } 149 150 public void compileAndRemove(Collection 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 f = new FileWriter (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 i = classes.iterator(); 172 while (i.hasNext()) { 173 String className = (String ) i.next(); 174 Class cl; 175 try { 176 cl = loadClass(className); 177 } catch (ClassNotFoundException 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 [] 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 e) { 192 throw new CompilerException(genConf, e); 193 } 194 } 195 196 public Class loadClass(String className) throws ClassNotFoundException { 197 return classLoader.loadClass(className); 198 } 199 200 public static boolean isRemoteItf(Class cl) { 201 if (!cl.isInterface() || !Remote .class.isAssignableFrom(cl)) { 203 return false; 204 } 205 206 Method [] m = cl.getMethods(); 208 for (int i=0; i<m.length; i++) { 209 Class [] ex = m[i].getExceptionTypes(); 210 int j = 0; 211 while ((j < ex.length) && !RemoteException .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 getRemoteItfs(Class cl) { 222 Set remItfs = new HashSet (); 223 while (cl != null) { 224 Class [] itfs = cl.getInterfaces(); 225 if (isRemoteItf(cl)) { 226 remItfs.add(cl); 227 } 228 for (int i=0; i<itfs.length; i++) { 229 Class 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 { 240 public int compare(Object o1, Object o2) { 241 Method m1 = (Method )o1; 242 Method m2 = (Method )o2; 243 int r = m1.getName().compareTo(m2.getName()); 244 if (r != 0) return r; 245 Class [] p1 = m1.getParameterTypes(); 246 Class [] 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 public static Method [] getRemoteMethods(Class cl) { 267 TreeSet remMethods = new TreeSet (methodComparator); 268 Set itfs = getRemoteItfs(cl); 270 TreeSet itfMethods = new TreeSet (methodComparator); 271 Iterator it = itfs.iterator(); 272 while (it.hasNext()) { 273 Class itf = (Class ) it.next(); 274 Method [] m = itf.getMethods(); 275 for (int i=0; i<m.length; i++) { 276 itfMethods.add(m[i]); 277 } 278 } 279 280 TreeSet clMethods = new TreeSet (methodComparator); 281 Method [] methods = cl.getMethods(); 282 for (int i=0; i<methods.length; i++) { 283 clMethods.add(methods[i]); 284 } 285 286 Iterator i1 = clMethods.iterator(); 287 Iterator i2 = itfMethods.iterator(); 288 if (i1.hasNext() && i2.hasNext()) { 289 Method m1 = (Method ) i1.next(); 290 Method m2 = (Method ) i2.next(); 291 do { 292 int d = methodComparator.compare(m1, m2); 293 if (d > 0) { 294 m2 = (i2.hasNext()) ? (Method )i2.next() : null; 295 } else if (d < 0) { 296 m1 = (i1.hasNext()) ? (Method )i1.next() : null; 297 } else { 298 remMethods.add(m2); 300 m1 = (i1.hasNext()) ? (Method )i1.next() : null; 301 m2 = (i2.hasNext()) ? (Method )i2.next() : null; 302 } 303 } while ((m1 != null) && (m2 != null)); 304 } 305 306 int i = remMethods.size(); 307 Method [] m = new Method [i]; 308 it = remMethods.iterator(); 309 i = 0; 310 while (it.hasNext()) { 311 m[i++] = (Method ) it.next(); 312 } 313 return m; 314 } 315 316 public static ClassLoader buildClassLoader(String classPath) { 317 String classpath = classPath + System.getProperty("path.separator", "") + System.getProperty("java.class.path", ""); 318 Vector nurls = new Vector (); 319 StringTokenizer st = new StringTokenizer (classpath, System.getProperty("path.separator", "")); 320 while (st.hasMoreTokens()) { 321 String url = st.nextToken(); 322 if (!url.equals("")) { 323 try { 324 URL u = (new File (url)).toURL(); 325 nurls.addElement(u); 326 } catch (MalformedURLException e) { 327 } 329 } 330 } 331 if (nurls.size() == 0) { 332 return Thread.currentThread().getContextClassLoader(); 333 } 334 URL urls[] = new URL [nurls.size()]; 335 nurls.copyInto(urls); 336 return new URLClassLoader (urls, null); 337 } 338 339 public static void usage() { 340 System.out.println( 341 "Usage: java " 342 + MethodProto.getName(Compiler .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 [] args) throws CompilerException { 362 Compiler cc = new Compiler (); 363 cc.configure(args); 364 cc.run(); 365 } 366 367 public static void main(String [] args) { 368 if (args.length == 0) { 369 usage(); 370 return; 371 } 372 try { 373 generate(args); 374 } catch (Exception e) { 375 e.printStackTrace(); 376 System.exit(1); 377 } 378 } 379 380 public String getSrcDir() { 381 return srcDir; 382 } 383 384 public boolean isCompile() { 385 return !noc; 386 } 387 388 public String getCompiler() { 389 return compiler; 390 } 391 392 public String getDestDir() { 393 return destDir; 394 } 395 396 public String getClassPath() { 397 return classPath; 398 } 399 400 public boolean isInvokeCmd() { 401 return invokeCmd; 402 } 403 } 404 | Popular Tags |