| 1 18 19 package org.objectweb.jac.ide; 20 21 import com.sun.tools.javac.Main; 22 import gnu.regexp.RE; 23 import gnu.regexp.REException; 24 import gnu.regexp.REMatch; 25 import java.io.BufferedReader; 26 import java.io.ByteArrayInputStream; 27 import java.io.ByteArrayOutputStream; 28 import java.io.FileInputStream; 29 import java.io.FileNotFoundException; 30 import java.io.FileOutputStream; 31 import java.io.FileWriter; 32 import java.io.FilenameFilter; 33 import java.io.IOException; 34 import java.io.InputStreamReader; 35 import java.io.PrintStream; 36 import java.io.Writer; 37 import java.util.Arrays; 38 import java.util.Collection; 39 import java.util.HashSet; 40 import java.util.Hashtable; 41 import java.util.Iterator; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.Set; 45 import java.util.Vector; 46 import java.util.jar.JarEntry; 47 import java.util.jar.JarOutputStream; 48 import java.util.jar.Manifest; 49 import org.apache.log4j.Logger; 50 import org.objectweb.jac.core.rtti.MethodItem; 51 import org.objectweb.jac.core.rtti.NamingConventions; 52 import org.objectweb.jac.lib.Attachment; 53 import org.objectweb.jac.util.Classes; 54 import org.objectweb.jac.util.File; 55 import org.objectweb.jac.util.Files; 56 import org.objectweb.jac.util.LineNumberWriter; 57 import org.objectweb.jac.util.Streams; 58 import org.objectweb.jac.util.Strings; 59 60 public class CodeGeneration { 61 static Logger logger = Logger.getLogger("ide.compile"); 62 63 69 public static void createProjectCode(Project project, String baseDir) 70 throws CannotGenerateException, IOException 71 { 72 createJavaCode(project,baseDir); 73 Iterator it = project.getApplications().iterator(); 74 while(it.hasNext()) { 75 Application cur = (Application)it.next(); 76 createApplicationCode(project, cur, new File(baseDir,cur.getGenerationName())); 77 } 78 print("generation completed for "+project.getName()+"."); 79 } 80 81 86 public static void createJavaCode(Project project, String baseDir) 87 throws CannotGenerateException, IOException, FileNotFoundException 88 { 89 Iterator it = Projects.types.getEnumeratedTypes().iterator(); 90 while(it.hasNext()) { 91 EnumeratedType enum = (EnumeratedType)it.next(); 92 createEnumCode(enum, new File(baseDir,enum.getPackagePath())); 93 } 94 it = project.getPackages().iterator(); 95 while(it.hasNext()) { 96 Package cur = (Package)it.next(); 97 createPackageCode(project, cur, 98 new File(baseDir,cur.getGenerationName()), 99 cur.getGenerationName()); 100 } 101 } 102 103 109 public static void createEnumCode(EnumeratedType enum, File dir) throws IOException { 110 print("Generating code for enum "+enum.getName()+"."); 111 dir.mkdirs(); 112 String enumName = Strings.toUSAscii(enum.getName()); 113 FileWriter out = new FileWriter(new File(dir, enumName+".java")); 114 try { 115 out.write("package "+enum.getPackagePath()+";\n"); 116 out.write("public interface "+enumName+" {\n"); 117 int value = enum.getStartValue(); 118 int step = enum.getStep(); 119 Iterator it = enum.getNames().iterator(); 120 while (it.hasNext()) { 121 StringBuffer nameBuf = new StringBuffer((String)it.next()); 122 Strings.toUSAscii(nameBuf); 123 Strings.toUpperCase(nameBuf); 124 Strings.replace(" '-/+",'_',nameBuf); 125 Strings.deleteChars("()[]",nameBuf); 126 String name = nameBuf.toString(); 127 StringBuffer buffer = new StringBuffer(name.length()); 129 for (int i=0; i<name.length(); i++) { 130 char c = name.charAt(i); 131 if (c != '.') 132 buffer.append(c); 133 } 134 name = buffer.toString(); 135 out.write(" int "+(Character.isDigit(name.charAt(0))?"_":"")+name+" = "+value+";\n"); 136 value += step; 137 } 138 out.write("}\n"); 139 } finally { 140 out.close(); 141 } 142 } 143 144 152 public static void createApplicationCode(Project prj, 153 Application app, 154 File baseDir) 155 throws CannotGenerateException, IOException 156 { 157 Iterator it = app.getAspectConfigurations().iterator(); 158 while (it.hasNext()) { 159 AspectConfiguration ac = (AspectConfiguration) it.next(); 160 createACFile(prj,ac,baseDir); 161 } 163 createJACFile(prj,app,baseDir); 164 } 165 166 171 static void writeWarning(Writer fw) { 172 try { 173 fw.write("//\n"+ 174 "// WARNING: this file has been automatically generated by JAC\n"+ 175 "// DO NOT MODIFY unless you know what you are doing\n"+ 176 "//\n"); 177 } catch(Exception e) { 178 e.printStackTrace(); 179 } 180 } 181 182 static transient Map aspectPlugins = new Hashtable(); 184 static { 185 aspectPlugins.put("rtti", new RttiPlugin()); 186 aspectPlugins.put("gui", new GuiPlugin()); 188 aspectPlugins.put("persistence", new PersistencePlugin()); 189 } 190 191 198 static void createACFile(Project project, 199 AspectConfiguration ac, File dir) { 200 try { 201 File f = new File(dir,ac.getGenerationName()+".acc"); 202 if (f.exists()) 203 f.delete(); 204 f.getParentFile().mkdirs(); 205 f.createNewFile(); 206 FileWriter fw = new FileWriter(f); 207 208 if (aspectPlugins.containsKey(ac.getName())) { 210 AspectPlugin plugin = 211 (AspectPlugin)aspectPlugins.get(ac.getName()); 212 plugin.genConfig(fw,project); 213 } 214 215 if (ac.getDefaultConfigurationCode()!=null && 217 !ac.getDefaultConfigurationCode().equals("")) { 218 Collection classes = createClassesList(project); 219 Iterator itClasses = classes.iterator(); 220 while(itClasses.hasNext()) { 221 String classname = (String)itClasses.next(); 222 fw.write("class "+classname+" {\n"); 223 fw.write(ac.getDefaultConfigurationCode()); 224 fw.write("\n}\n"); 225 } 226 } 227 228 List configItems = project.getConfigItems(); 231 Iterator ite = configItems.iterator(); 232 fw.write("//CodeGeneration : generate Project code\n"); 233 while (ite.hasNext()){ 234 ConfigItem configItem = (ConfigItem)ite.next(); 235 if (configItem.getAspectConfiguration()==ac){ 236 fw.write(configItem.getMethod()+" "+translateParam(configItem)); 237 } 238 } 239 fw.write("//CodeGeneration : end of Project code\n\n"); 240 ite = project.getPackages().iterator(); 242 fw.write("//CodeGeneration : generate Package code\n"); 243 while(ite.hasNext()){ 244 Package pack = (Package)ite.next(); 245 generateConfigItemPackageCode(pack,ac,fw); 246 } 247 fw.write("//CodeGeneration : end of Package code\n\n"); 248 fw.write(ac.getConfigurationCode()); 250 fw.close(); 251 } catch(Exception e) { 252 e.printStackTrace(); 253 } 254 } 255 256 264 static Collection createClassesList(Project project) { 265 Vector result = new Vector(); 266 Iterator it = project.getPackages().iterator(); 267 while(it.hasNext()) { 268 Package cur = (Package)it.next(); 269 result.addAll(createClassesList(cur,cur.getGenerationName())); 270 } 271 return result; 272 } 273 274 282 static Collection createClassesList(Package project,String baseDir) { 283 Vector result = new Vector(); 284 Iterator it = project.getSubPackages().iterator(); 285 while(it.hasNext()) { 286 Package cur = (Package)it.next(); 287 result.addAll(createClassesList(cur,baseDir+"."+cur.getGenerationName())); 288 } 289 it = project.getClasses().iterator(); 290 while(it.hasNext()) { 291 Class cur = (Class)it.next(); 292 result.add(baseDir+"."+cur.getGenerationName()); 293 } 294 return result; 295 } 296 297 304 305 static void createJACFile(Project prj, Application app, File baseDir) 306 throws CannotGenerateException, IOException 307 { 308 File f = app.getJacFile(); 309 if (f.exists()) 310 f.delete(); 311 f.getParentFile().mkdirs(); 312 f.createNewFile(); 313 FileWriter fw = new FileWriter(f); 314 315 if (app.getMainClass()==null) { 316 throw new CannotGenerateException("No main class defined."); 317 } 318 fw.write("applicationName: "+app.getName()+"\n"+ 319 "launchingClass: "+app.getMainClass().getGenerationFullName()+"\n"); 320 321 if (app.getAspectConfigurations()!=null && 322 app.getAspectConfigurations().size()>0) { 323 fw.write( "aspects: "); 324 if (app.getAspectConfigurations().size()>0 && 325 !((AspectConfiguration)app.getAspectConfigurations().get(0)) 326 .getName().equals("rtti")) 327 { 328 fw.write( "rtti" 329 + " \"" + app.getGenerationName() 330 + "/" + "null.acc\"" 331 + " true "); 332 } 333 Iterator it = app.getAspectConfigurations().iterator(); 334 while(it.hasNext()) { 335 AspectConfiguration cur = (AspectConfiguration)it.next(); 336 if( ((org.objectweb.jac.core.ACManager)org.objectweb.jac.core.ACManager.get()) 337 .isACDeclared(cur.getName()) ) { 338 fw.write( cur.getName() 339 + " \"" + app.getGenerationName() 340 + "/" + cur.getGenerationName() + ".acc\"" 341 + " " + cur.isWoven() + " "); 342 } else { 343 fw.write( cur.getAspect().getGenerationFullName()+"AC" 344 + " \"" + app.getGenerationName() 345 + "/" + cur.getGenerationName() + ".acc\"" 346 + " " + cur.isWoven() + " "); 347 } 348 } 349 fw.write("\n\n"); 350 } 351 352 if (app.getHosts()!=null && app.getHosts().size()>0) { 353 fw.write( "\ntopology: "); 354 Iterator it = app.getHosts().iterator(); 355 while(it.hasNext()) { 356 String cur=(String)it.next(); 357 fw.write(cur+" "); 358 } 359 fw.write("\n\n"); 360 } 361 362 if (!app.getIgnoredClasses().isEmpty()) { 363 fw.write("\njac.toNotAdapt: "); 364 Iterator it = app.getIgnoredClasses().iterator(); 365 while(it.hasNext()) { 366 String expr = (String)it.next(); 367 fw.write(expr+" "); 368 } 369 fw.write("\n\n"); 370 } 371 372 fw.close(); 373 } 374 375 383 public static void createPackageCode(Project prj, 384 Package pkg, 385 File baseDir, 386 String ppath) 387 throws FileNotFoundException, IOException 388 { 389 baseDir.mkdirs(); 390 391 Iterator it = pkg.getSubPackages().iterator(); 392 while (it.hasNext()) { 393 Package cur = (Package)it.next(); 394 createPackageCode(prj, cur, 395 new File(baseDir,cur.getGenerationName()), 396 ppath+"."+cur.getGenerationName()); 397 } 398 it = pkg.getClasses().iterator(); 399 while (it.hasNext()) { 400 Class cur = (Class)it.next(); 401 if (cur instanceof Aspect) { 402 createAspectCode(prj,(Aspect)cur,baseDir,ppath); 403 } else { 404 createClassCode(prj,cur,baseDir,ppath); 405 } 406 } 407 408 it = pkg.getResources().iterator(); 409 while (it.hasNext()) { 410 Attachment res = (Attachment)it.next(); 411 FileOutputStream out = new FileOutputStream(new File(baseDir,res.getName())); 412 try { 413 byte[] data = res.getData(); 414 out.write(data,0,data.length); 415 } finally { 416 out.close(); 417 } 418 } 419 } 420 421 static transient Hashtable classesLineNumbers = new Hashtable(); 423 424 428 public static Map getClassLineNumbers(Class c) { 429 Map map = (Map)classesLineNumbers.get(c); 430 if (map==null) { 431 map = new Hashtable(); 432 classesLineNumbers.put(c,map); 433 } 434 return map; 435 } 436 437 445 public static void createClassCode(Project prj, Class c, 446 File baseDir, String ppath) { 447 try { 448 Map lineNumbers = getClassLineNumbers(c); 449 lineNumbers.clear(); 450 print("generating "+c.getFullName()); 451 File f = new File(baseDir,c.getGenerationName()+".java"); 452 classFiles.put(f.getAbsolutePath(),c); 453 if (f.exists()) 454 f.delete(); 455 f.getParentFile().mkdirs(); 456 f.createNewFile(); 457 String shortName = c.getGenerationName(); 458 LineNumberWriter output = new LineNumberWriter(Files.newFileWriter(f,"UTF-8")); 459 writeWarning(output); 460 output.write("\npackage "+ppath+";\n\n"); 461 String description = c.getDescription(); 462 463 HashSet generatedImports = new HashSet(); 464 Iterator it = c.getFields().iterator(); 466 while(it.hasNext()) { 467 Type type = ((Field)it.next()).getType(); 468 if (!(type instanceof EnumeratedType) && 469 type.getPackagePath()!=null && !type.getPackagePath().equals("") 470 && !generatedImports.contains(type.getGenerationFullName())) { 471 output.write("import "+type.getGenerationFullName()+";\n"); 472 generatedImports.add(type.getGenerationFullName()); 473 } 474 } 475 476 it = c.getImports().iterator(); 478 while(it.hasNext()) { 479 String imp = (String)it.next(); 480 if (!generatedImports.contains(imp)) { 481 output.write("import "+imp+";\n"); 482 generatedImports.add(imp); 483 } 484 } 485 486 if (description!=null && description.length()>0) 487 output.write("\n/**\n"+description+"\n*/\n"); 488 boolean isInterface = c instanceof Interface; 489 output.write("\npublic "+(c.isAbstract()?"abstract ":"")+ 490 (isInterface?"interface ":"class ")+ 491 shortName+ 492 ((c.getSuperClass() == null)?"":" extends "+ 493 c.getSuperClass().getGenerationFullName())); 494 Set interfaces = c.getInterfaces(); 495 if (!interfaces.isEmpty()) { 496 if (isInterface) 497 output.write(" extends "); 498 else 499 output.write(" implements "); 500 joinFullNames(output,interfaces,","); 501 } 502 output.write( " {\n" ); 503 List ms = c.getMethods(); 504 for (int i=0; i < ms.size(); i++) { 505 Method method = (Method)ms.get(i); 506 createMethodCode(output,lineNumbers,method,isInterface); 507 } 508 509 List fs = c.getFields(); 510 for (int i=0; i<fs.size(); i++) { 511 Field field = (Field)fs.get(i); 512 createFieldCode(output,lineNumbers,field,isInterface); 513 } 514 515 List rs = c.getLinks(); 516 for (int i=0; i<rs.size(); i++) { 517 Role role = (Role)rs.get(i); 518 if (role instanceof RelationRole) { 519 RelationRole relRole = (RelationRole)role; 520 RelationLink rel = (RelationLink)role.getLink(); 521 if (relRole.isNavigable()) { 522 createRelationCode(output,lineNumbers,rel,relRole,isInterface); 523 } 524 } 525 } 526 527 output.write("}\n"); 528 output.close(); 529 } catch( Exception e) { 531 e.printStackTrace(); 532 } 533 } 534 535 543 public static void createFieldCode(LineNumberWriter output, 544 Map lineNumbers, 545 Field field, 546 boolean isInterface) 547 throws IOException 548 { 549 String fieldName = field.getGenerationName(); 550 String type = field.getType().getGenerationFullName(); 551 552 if (!(field.isCalculated() || isInterface)) { 553 String description = field.getDescription(); 554 if (description!=null && description.length()>0) 555 output.write("\n/**\n" + description + "\n*/\n"); 556 lineNumbers.put(field,new Integer(output.getLines())); 557 output.write("\n " + field.getPrototype()); 558 String defaultValue = field.getDefaultValue(); 559 if (defaultValue!=null && !defaultValue.equals("")) { 560 output.write(" = "+defaultValue); 561 } 562 output.write(";\n"); 563 } 564 565 boolean isStatic = field.isStatic(); 566 if (!field.isReadOnly()) { 567 Setter setter = field.getSetter(); 568 if (setter==null) { 569 output.write("\n /**\n"+ 570 " * Sets the value of field "+fieldName+".\n"+ 571 " * @param "+fieldName+" value of field "+fieldName+ 572 "\n */\n"); 573 lineNumbers.put(field,new Integer(output.getLines())); 574 createSetter( 575 output,fieldName,type, isStatic, 576 field.isStatic()?field.getParent().getGenerationFullName():null, 577 isInterface); 578 } else { 579 createMethodCode(output,lineNumbers,setter,isInterface); 580 } 581 } 582 583 Getter getter = field.getGetter(); 584 if (getter==null) { 585 if (!field.isCalculated()) { 586 output.write("\n /**\n"+ 587 " * Gets the value of field "+fieldName+".\n"+ 588 " * @return value of field "+fieldName+ 589 "\n */\n"); 590 lineNumbers.put(field,new Integer(output.getLines())); 591 createGetter( 592 output,fieldName,type,isStatic, 593 field.isStatic()?field.getParent().getGenerationFullName():null, 594 isInterface); 595 } 596 } else { 597 createMethodCode(output,lineNumbers,field.getGetter(),isInterface); 598 } 599 } 600 601 public static void createRelationCode(LineNumberWriter output, 602 Map lineNumbers, 603 RelationLink rel, 604 RelationRole role, 605 boolean isInterface) 606 throws IOException 607 { 608 String roleGen = role.getGenerationName(); 609 String type = role.getAbstractType().getGenerationFullName(); 610 boolean isCalculated = rel.isCalculated(); 611 if (!isCalculated) { 612 output.write("\n " + role.getPrototype()+";\n"); 613 createSetter(output,roleGen,type,false,null,isInterface); 614 } 615 Method getter = role.getGetter(); 616 if (getter==null && !isCalculated) { 617 createGetter(output,roleGen,type,false,null,isInterface); 618 } else if (getter!=null) { 619 createMethodCode(output,lineNumbers,getter,isInterface); 620 } 621 622 if (role.isMultiple() && !isCalculated) { 623 Typed primaryKey = role.getPrimaryKey(); 624 type = role.getEnd().getGenerationFullName(); 625 626 Method adder = role.getAdder(); 627 if (adder==null) { 628 createAdder(output,roleGen,type,primaryKey); 629 } else { 630 createMethodCode(output,lineNumbers,adder,isInterface); 631 } 632 633 Method remover = role.getRemover(); 634 if (remover==null) { 635 createRemover(output,roleGen,type,primaryKey); 636 } else { 637 createMethodCode(output,lineNumbers,remover,isInterface); 638 } 639 640 Method clearer = role.getClearer(); 641 if (clearer==null) { 642 createClearer(output,roleGen); 643 } else { 644 createMethodCode(output,lineNumbers,clearer,isInterface); 645 } 646 if (primaryKey!=null) { 647 createIndexGetter(output,role); 648 } 649 } 650 } 651 652 659 public static void createMethodCode(LineNumberWriter output, 660 Map lineNumbers, 661 Method method, 662 boolean isInterface) 663 throws IOException 664 { 665 output.write("\n/**\n"); 666 String description = method.getDescription(); 667 if (description!=null) { 668 output.write(description); 669 } 670 Iterator params = method.getParameters().iterator(); 671 while (params.hasNext()) { 672 Parameter param = (Parameter)params.next(); 673 output.write("\n@param "+param.getGenerationName()+" "+ 674 param.getDescription()); 675 } 676 output.write("\n*/\n"); 677 lineNumbers.put(method,new Integer(output.getLines())); 678 output.write("\n "+method.getModifiers()+" "+ 681 method.getPrototype()); 682 if (method.isAbstract() || isInterface) { 683 output.write(";\n"); 684 } else { 685 output.write(" {"); 686 String body = method.getBody(); 687 if (body!=null) 688 output.write( "\n "+body); 689 output.write("\n }\n"); 690 } 691 } 692 693 701 public static void createAspectCode(Project prj,Aspect a, 702 File baseDir,String ppath) { 703 try { 704 print("generating "+a.getName()); 705 File f = new File(baseDir,a.getGenerationName() + "AC.java"); 706 if (f.exists()) 707 f.delete(); 708 f.getParentFile().mkdirs(); 709 f.createNewFile(); 710 String shortName = a.getGenerationName(); 711 FileWriter fw = new FileWriter(f); 712 writeWarning(fw); 713 fw.write( "\npackage "+ppath+";\n" ); 714 fw.write( "import org.objectweb.jac.core.*;\n" ); 715 fw.write( "import org.objectweb.jac.core.rtti.*;\n" ); 716 fw.write( "import org.objectweb.jac.util.*;\n" ); 717 fw.write( "\npublic class "+shortName+ 718 "AC extends org.objectweb.jac.core.AspectComponent"); 719 fw.write( " {\n" ); 720 fw.write( "\n public "+shortName+"AC() {"); 721 Iterator it = a.getPointcutLinks().iterator(); 722 while(it.hasNext()) { 723 PointcutLink pc = (PointcutLink)it.next(); 724 if(pc.getEnd() instanceof org.objectweb.jac.ide.Class) { 725 fw.write("\n pointcut(\""+ 726 "ALL\",\""+ 727 ((org.objectweb.jac.ide.Class)pc.getEnd()).getGenerationFullName()+"\",\""+ 728 pc.getMethodPCD()+"\","+ 729 "new "+shortName+"Wrapper(this)"+",\""+ 730 pc.getAspectRole()+"\",\""+ 731 pc.getHostPCD()+"\",null);"); 732 } else if (pc.getEnd() instanceof Instance) { 733 fw.write("\n pointcut(\""+ 734 ((Instance)pc.getEnd()).getGenerationName()+"\",\""+ 735 ((org.objectweb.jac.ide.Class)((Instance)pc.getEnd()).getType()).getGenerationName()+"\",\""+ 736 pc.getMethodPCD()+"\"," |