001 /* 002 Copyright (C) 2002-2003 Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.ide; 020 021 import com.sun.tools.javac.Main; 022 import gnu.regexp.RE; 023 import gnu.regexp.REException; 024 import gnu.regexp.REMatch; 025 import java.io.BufferedReader; 026 import java.io.ByteArrayInputStream; 027 import java.io.ByteArrayOutputStream; 028 import java.io.FileInputStream; 029 import java.io.FileNotFoundException; 030 import java.io.FileOutputStream; 031 import java.io.FileWriter; 032 import java.io.FilenameFilter; 033 import java.io.IOException; 034 import java.io.InputStreamReader; 035 import java.io.PrintStream; 036 import java.io.Writer; 037 import java.util.Arrays; 038 import java.util.Collection; 039 import java.util.HashSet; 040 import java.util.Hashtable; 041 import java.util.Iterator; 042 import java.util.List; 043 import java.util.Map; 044 import java.util.Set; 045 import java.util.Vector; 046 import java.util.jar.JarEntry; 047 import java.util.jar.JarOutputStream; 048 import java.util.jar.Manifest; 049 import org.apache.log4j.Logger; 050 import org.objectweb.jac.core.rtti.MethodItem; 051 import org.objectweb.jac.core.rtti.NamingConventions; 052 import org.objectweb.jac.lib.Attachment; 053 import org.objectweb.jac.util.Classes; 054 import org.objectweb.jac.util.File; 055 import org.objectweb.jac.util.Files; 056 import org.objectweb.jac.util.LineNumberWriter; 057 import org.objectweb.jac.util.Streams; 058 import org.objectweb.jac.util.Strings; 059 060 public class CodeGeneration { 061 static Logger logger = Logger.getLogger("ide.compile"); 062 063 /** 064 * Generate code for all the classes and aspects of a project. 065 * 066 * @param project the project 067 * @param baseDir base directory where to put generated files 068 */ 069 public static void createProjectCode(Project project, String baseDir) 070 throws CannotGenerateException, IOException 071 { 072 createJavaCode(project,baseDir); 073 Iterator it = project.getApplications().iterator(); 074 while(it.hasNext()) { 075 Application cur = (Application)it.next(); 076 createApplicationCode(project, cur, new File(baseDir,cur.getGenerationName())); 077 } 078 print("generation completed for "+project.getName()+"."); 079 } 080 081 public static void createJavaCode(Project project,String baseDir) 082 throws CannotGenerateException, IOException, FileNotFoundException 083 { 084 Iterator it = Projects.types.getEnumeratedTypes().iterator(); 085 while(it.hasNext()) { 086 EnumeratedType enum = (EnumeratedType)it.next(); 087 createEnumCode(enum, new File(baseDir,enum.getPackagePath())); 088 } 089 it = project.getPackages().iterator(); 090 while(it.hasNext()) { 091 Package cur = (Package)it.next(); 092 createPackageCode(project, cur, 093 new File(baseDir,cur.getGenerationName()), 094 cur.getGenerationName()); 095 } 096 } 097 098 public static void createEnumCode(EnumeratedType enum, File dir) throws IOException { 099 print("Generating code for enum "+enum.getName()+"."); 100 String enumName = Strings.toUSAscii(enum.getName()); 101 FileWriter out = new FileWriter(new File(dir, enumName+".java")); 102 try { 103 out.write("package "+enum.getPackagePath()+";\n"); 104 out.write("public interface "+enumName+" {\n"); 105 int value = enum.getStartValue(); 106 int step = enum.getStep(); 107 Iterator it = enum.getNames().iterator(); 108 while (it.hasNext()) { 109 StringBuffer nameBuf = new StringBuffer((String)it.next()); 110 Strings.toUSAscii(nameBuf); 111 Strings.toUpperCase(nameBuf); 112 Strings.replace(" '-/+",'_',nameBuf); 113 Strings.deleteChars("()[]",nameBuf); 114 String name = nameBuf.toString(); 115 // remove unwanted characters such as '.' 116 StringBuffer buffer = new StringBuffer(name.length()); 117 for (int i=0; i<name.length(); i++) { 118 char c = name.charAt(i); 119 if (c != '.') 120 buffer.append(c); 121 } 122 name = buffer.toString(); 123 out.write(" int "+(Character.isDigit(name.charAt(0))?"_":"")+name+" = "+value+";\n"); 124 value += step; 125 } 126 out.write("}\n"); 127 } finally { 128 out.close(); 129 } 130 } 131 132 /** 133 * Generate code for an application (<code>Run</code> and aspect 134 * configurations) 135 * 136 * @param prj the project 137 * @param app the application 138 * @param baseDir the base directory where to put the generated files 139 */ 140 public static void createApplicationCode(Project prj, 141 Application app, 142 File baseDir) 143 throws CannotGenerateException, IOException 144 { 145 Iterator it = app.getAspectConfigurations().iterator(); 146 while (it.hasNext()) { 147 AspectConfiguration ac = (AspectConfiguration) it.next(); 148 createACFile(prj,ac,baseDir); 149 //createDefaultACFile(prj,ac,baseDir); 150 } 151 createJACFile(prj,app,baseDir); 152 } 153 154 /** 155 * Generate a warning that the file was automatically generated. 156 * 157 * @param writer writer where to write the warning 158 */ 159 static void writeWarning(Writer fw) { 160 try { 161 fw.write("//\n"+ 162 "// WARNING: this file has been automatically generated by JAC\n"+ 163 "// DO NOT MODIFY unless you know what you are doing\n"+ 164 "//\n"); 165 } catch(Exception e) { 166 e.printStackTrace(); 167 } 168 } 169 170 // aspect name -> AspectPlugin 171 static transient Map aspectPlugins = new Hashtable(); 172 static { 173 aspectPlugins.put("rtti", new RttiPlugin()); 174 //aspectPlugins.put("integrity", new IntegrityPlugin()); 175 aspectPlugins.put("gui", new GuiPlugin()); 176 aspectPlugins.put("persistence", new PersistencePlugin()); 177 } 178 179 /** 180 * Generate aspect configuration code for an aspect of a project. 181 * 182 * @param project the project 183 * @param ac the aspect configuration 184 * @param dir directory where to put the file 185 */ 186 static void createACFile(Project project, 187 AspectConfiguration ac, File dir) { 188 try { 189 File f = new File(dir,ac.getGenerationName()+".acc"); 190 if (f.exists()) 191 f.delete(); 192 f.getParentFile().mkdirs(); 193 f.createNewFile(); 194 FileWriter fw = new FileWriter(f); 195 196 // Automatically generated config code 197 if (aspectPlugins.containsKey(ac.getName())) { 198 AspectPlugin plugin = 199 (AspectPlugin)aspectPlugins.get(ac.getName()); 200 plugin.genConfig(fw,project); 201 } 202 203 // common default configurations for all classes 204 if (ac.getDefaultConfigurationCode()!=null && 205 !ac.getDefaultConfigurationCode().equals("")) { 206 Collection classes = createClassesList(project); 207 Iterator itClasses = classes.iterator(); 208 while(itClasses.hasNext()) { 209 String classname = (String)itClasses.next(); 210 fw.write("class "+classname+" {\n"); 211 fw.write(ac.getDefaultConfigurationCode()); 212 fw.write("\n}\n"); 213 } 214 } 215 216 //Create Acc ConfigurationCode from the ConfigItem 217 //First creating code from the Project 218 List configItems = project.getConfigItems(); 219 Iterator ite = configItems.iterator(); 220 fw.write("//CodeGeneration : generate Project code\n"); 221 while (ite.hasNext()){ 222 ConfigItem configItem = (ConfigItem)ite.next(); 223 if (configItem.getAspectConfiguration()==ac){ 224 fw.write(configItem.getMethod()+" "+translateParam(configItem)); 225 } 226 } 227 fw.write("//CodeGeneration : end of Project code\n\n"); 228 //Iterate on each package of the project 229 ite = project.getPackages().iterator(); 230 fw.write("//CodeGeneration : generate Package code\n"); 231 while(ite.hasNext()){ 232 Package pack = (Package)ite.next(); 233 generateConfigItemPackageCode(pack,ac,fw); 234 } 235 fw.write("//CodeGeneration : end of Package code\n\n"); 236 // main config 237 fw.write(ac.getConfigurationCode()); 238 fw.close(); 239 } catch(Exception e) { 240 e.printStackTrace(); 241 } 242 } 243 244 /** 245 * Build a list of paths for all the classes of a project. 246 * 247 * @param project the project 248 * @return a collection of Strings which are the paths of the 249 * source files of the classes 250 * @see createClassesList(Package,String) 251 */ 252 static Collection createClassesList(Project project) { 253 Vector result = new Vector(); 254 Iterator it = project.getPackages().iterator(); 255 while(it.hasNext()) { 256 Package cur = (Package)it.next(); 257 result.addAll(createClassesList(cur,cur.getGenerationName())); 258 } 259 return result; 260 } 261 262 /** 263 * Build a list of paths for all the classes of a package and its 264 * subpackages. 265 * 266 * @param package the package 267 * @return a collection of Strings which are the paths of the 268 * source files of the classes 269 */ 270 static Collection createClassesList(Package project,String baseDir) { 271 Vector result = new Vector(); 272 Iterator it = project.getSubPackages().iterator(); 273 while(it.hasNext()) { 274 Package cur = (Package)it.next(); 275 result.addAll(createClassesList(cur,baseDir+"."+cur.getGenerationName())); 276 } 277 it = project.getClasses().iterator(); 278 while(it.hasNext()) { 279 Class cur = (Class)it.next(); 280 result.add(baseDir+"."+cur.getGenerationName()); 281 } 282 return result; 283 } 284 285 /** 286 * Generate the descriptor of an application (the .jac file). 287 * 288 * @param prj the project 289 * @param app the applicatino 290 * @param baseDir directory where to put the <code>.jac</code> file 291 */ 292 293 static void createJACFile(Project prj, Application app, File baseDir) 294 throws CannotGenerateException, IOException 295 { 296 File f = app.getJacFile(); 297 if (f.exists()) 298 f.delete(); 299 f.getParentFile().mkdirs(); 300 f.createNewFile(); 301 FileWriter fw = new FileWriter(f); 302 303 if (app.getMainClass()==null) { 304 throw new CannotGenerateException("No main class defined."); 305 } 306 fw.write("applicationName: "+app.getName()+"\n"+ 307 "launchingClass: "+app.getMainClass().getGenerationFullName()+"\n"); 308 309 if (app.getAspectConfigurations()!=null && 310 app.getAspectConfigurations().size()>0) { 311 fw.write( "aspects: "); 312 if (app.getAspectConfigurations().size()>0 && 313 !((AspectConfiguration)app.getAspectConfigurations().get(0)) 314 .getName().equals("rtti")) 315 { 316 fw.write( "rtti" 317 + " \"" + app.getGenerationName() 318 + "/" + "null.acc\"" 319 + " true "); 320 } 321 Iterator it = app.getAspectConfigurations().iterator(); 322 while(it.hasNext()) { 323 AspectConfiguration cur = (AspectConfiguration)it.next(); 324 if( ((org.objectweb.jac.core.ACManager)org.objectweb.jac.core.ACManager.get()) 325 .isACDeclared(cur.getName()) ) { 326 fw.write( cur.getName() 327 + " \"" + app.getGenerationName() 328 + "/" + cur.getGenerationName() + ".acc\"" 329 + " " + cur.isWoven() + " "); 330 } else { 331 fw.write( cur.getAspect().getGenerationFullName()+"AC" 332 + " \"" + app.getGenerationName() 333 + "/" + cur.getGenerationName() + ".acc\"" 334 + " " + cur.isWoven() + " "); 335 } 336 } 337 fw.write("\n\n"); 338 } 339 340 if (app.getHosts()!=null && app.getHosts().size()>0) { 341 fw.write( "\ntopology: "); 342 Iterator it = app.getHosts().iterator(); 343 while(it.hasNext()) { 344 String cur=(String)it.next(); 345 fw.write(cur+" "); 346 } 347 fw.write("\n\n"); 348 } 349 350 if (!app.getIgnoredClasses().isEmpty()) { 351 fw.write("\njac.toNotAdapt: "); 352 Iterator it = app.getIgnoredClasses().iterator(); 353 while(it.hasNext()) { 354 String expr = (String)it.next(); 355 fw.write(expr+" "); 356 } 357 fw.write("\n\n"); 358 } 359 360 fw.close(); 361 } 362 363 /** 364 * Generate code for the classes of a package and its subpackages. 365 * 366 * @param prj the project 367 * @param pkg the package 368 * @param baseDir directory where to put the files of the package 369 * @param ppath java package path (<code>myapp.mypackage</code> for instance) 370 */ 371 public static void createPackageCode(Project prj, 372 Package pkg, 373 File baseDir, 374 String ppath) 375 throws FileNotFoundException, IOException 376 { 377 Iterator it = pkg.getSubPackages().iterator(); 378 while (it.hasNext()) { 379 Package cur = (Package)it.next(); 380 createPackageCode(prj, cur, 381 new File(baseDir,cur.getGenerationName()), 382 ppath+"."+cur.getGenerationName()); 383 } 384 it = pkg.getClasses().iterator(); 385 while (it.hasNext()) { 386 Class cur = (Class)it.next(); 387 if (cur instanceof Aspect) { 388 createAspectCode(prj,(Aspect)cur,baseDir,ppath); 389 } else { 390 createClassCode(prj,cur,baseDir,ppath); 391 } 392 } 393 394 it = pkg.getResources().iterator(); 395 while (it.hasNext()) { 396 Attachment res = (Attachment)it.next(); 397 FileOutputStream out = new FileOutputStream(new File(baseDir,res.getName())); 398 try { 399 byte[] data = res.getData(); 400 out.write(data,0,data.length); 401 } finally { 402 out.close(); 403 } 404 } 405 } 406 407 // Class -> ( Method -> (Integer)lineNumber ) 408 static transient Hashtable classesLineNumbers = new Hashtable(); 409 410 /** 411 * Returns a Map giving the line number of methods in the generated 412 * java source file. 413 */ 414 public static Map getClassLineNumbers(Class c) { 415 Map map = (Map)classesLineNumbers.get(c); 416 if (map==null) { 417 map = new Hashtable(); 418 classesLineNumbers.put(c,map); 419 } 420 return map; 421 } 422 423 /** 424 * Generate the java source code of a class. 425 * 426 * @param prj the project 427 * @param c the class 428 * @param baseDir directory where to put the generated file 429 * @param ppath java package path of the class 430 */ 431 public static void createClassCode(Project prj, Class c, 432 File baseDir, String ppath) { 433 try { 434 Map lineNumbers = getClassLineNumbers(c); 435 lineNumbers.clear(); 436 print("generating "+c.getFullName()); 437 File f = new File(baseDir,c.getGenerationName()+".java"); 438 classFiles.put(f.getAbsolutePath(),c); 439 if (f.exists()) 440 f.delete(); 441 f.getParentFile().mkdirs(); 442 f.createNewFile(); 443 String shortName = c.getGenerationName(); 444 LineNumberWriter output = new LineNumberWriter(Files.newFileWriter(f,"UTF-8")); 445 writeWarning(output); 446 output.write("\npackage "+ppath+";\n\n"); 447 String description = c.getDescription(); 448 449 HashSet generatedImports = new HashSet(); 450 // Automatic imports for field types 451 Iterator it = c.getFields().iterator(); 452 while(it.hasNext()) { 453 Type type = ((Field)it.next()).getType(); 454 if (!(type instanceof EnumeratedType) && 455 type.getPackagePath()!=null && !type.getPackagePath().equals("") 456 && !generatedImports.contains(type.getGenerationFullName())) { 457 output.write("import "+type.getGenerationFullName()+";\n"); 458 generatedImports.add(type.getGenerationFullName()); 459 } 460 } 461 462 // Imports of the class 463 it = c.getImports().iterator(); 464 while(it.hasNext()) { 465 String imp = (String)it.next(); 466 if (!generatedImports.contains(imp)) { 467 output.write("import "+imp+";\n"); 468 generatedImports.add(imp); 469 } 470 } 471 472 if (description!=null && description.length()>0) 473 output.write("\n/**\n"+description+"\n*/\n"); 474 boolean isInterface = c instanceof Interface; 475 output.write("\npublic "+(c.isAbstract()?"abstract ":"")+ 476 (isInterface?"interface ":"class ")+ 477 shortName+ 478 ((c.getSuperClass() == null)?"":" extends "+ 479 c.getSuperClass().getGenerationFullName())); 480 Set interfaces = c.getInterfaces(); 481 if (!interfaces.isEmpty()) { 482 if (isInterface) 483 output.write(" extends "); 484 else 485 output.write(" implements "); 486 joinFullNames(output,interfaces,","); 487 } 488 output.write( " {\n" ); 489 List ms = c.getMethods(); 490 for (int i=0; i < ms.size(); i++) { 491 Method method = (Method)ms.get(i); 492 createMethodCode(output,lineNumbers,method,isInterface); 493 } 494 495 List fs = c.getFields(); 496 for (int i=0; i<fs.size(); i++) { 497 Field field = (Field)fs.get(i); 498 createFieldCode(output,lineNumbers,field,isInterface); 499 } 500 501 List rs = c.getLinks(); 502 for (int i=0; i<rs.size(); i++) { 503 Role role = (Role)rs.get(i); 504 if (role instanceof RelationRole) { 505 RelationRole relRole = (RelationRole)role; 506 RelationLink rel = (RelationLink)role.getLink(); 507 if (relRole.isNavigable()) { 508 createRelationCode(output,lineNumbers,rel,relRole,isInterface); 509 } 510 } 511 } 512 513 output.write("}\n"); 514 output.close(); 515 //print("generation fullfilled."); 516 } catch( Exception e) { 517 e.printStackTrace(); 518 } 519 } 520 521 /** 522 * Generate the code for a field, its getter and its setter 523 * 524 * @param output where to write generated code 525 * @param lineNumbers line numbers information will be stored in this map 526 * @param field the field to generate code for 527 * @param isInterface wether the field belongs to an interface 528 */ 529 public static void createFieldCode(LineNumberWriter output, 530 Map lineNumbers, 531 Field field, 532 boolean isInterface) 533 throws IOException 534 { 535 String fieldName = field.getGenerationName(); 536 String type = field.getType().getGenerationFullName(); 537 538 if (!(field.isCalculated() || isInterface)) { 539 String description = field.getDescription(); 540 if (description!=null && description.length()>0) 541 output.write("\n/**\n" + description + "\n*/\n"); 542 lineNumbers.put(field,new Integer(output.getLines())); 543 output.write("\n " + field.getPrototype()); 544 String defaultValue = field.getDefaultValue(); 545 if (defaultValue!=null && !defaultValue.equals("")) { 546 output.write(" = "+defaultValue); 547 } 548 output.write(";\n"); 549 } 550 551 boolean isStatic = field.isStatic(); 552 if (!field.isReadOnly()) { 553 Setter setter = field.getSetter(); 554 if (setter==null) { 555 output.write("\n /**\n"+ 556 " * Sets the value of field "+fieldName+".\n"+ 557 " * @param "+fieldName+" value of field "+fieldName+ 558 "\n */\n"); 559 lineNumbers.put(field,new Integer(output.getLines())); 560 createSetter( 561 output,fieldName,type, isStatic, 562 field.isStatic()?field.getParent().getGenerationFullName():null, 563 isInterface); 564 } else { 565 createMethodCode(output,lineNumbers,setter,isInterface); 566 } 567 } 568 569 Getter getter = field.getGetter(); 570 if (getter==null) { 571 if (!field.isCalculated()) { 572 output.write("\n /**\n"+ 573 " * Gets the value of field "+fieldName+".\n"+ 574 " * @return value of field "+fieldName+ 575 "\n */\n"); 576 lineNumbers.put(field,new Integer(output.getLines())); 577 createGetter( 578 output,fieldName,type,isStatic, 579 field.isStatic()?field.getParent().getGenerationFullName():null, 580 isInterface); 581 } 582 } else { 583 createMethodCode(output,lineNumbers,field.getGetter(),isInterface); 584 } 585 } 586 587 public static void createRelationCode(LineNumberWriter output, 588 Map lineNumbers, 589 RelationLink rel, 590 RelationRole role, 591 boolean isInterface) 592 throws IOException 593 { 594 String roleGen = role.getGenerationName(); 595 String type = role.getAbstractType().getGenerationFullName(); 596 boolean isCalculated = rel.isCalculated(); 597 if (!isCalculated) { 598 output.write("\n " + role.getPrototype()+";\n"); 599 createSetter(output,roleGen,type,false,null,isInterface); 600 } 601 Method getter = role.getGetter(); 602 if (getter==null && !isCalculated) { 603 createGetter(output,roleGen,type,false,null,isInterface); 604 } else if (getter!=null) { 605 createMethodCode(output,lineNumbers,getter,isInterface); 606 } 607 608 if (role.isMultiple() && !isCalculated) { 609 Typed primaryKey = role.getPrimaryKey(); 610 type = role.getEnd().getGenerationFullName(); 611 612 Method adder = role.getAdder(); 613 if (adder==null) { 614 createAdder(output,roleGen,type,primaryKey); 615 } else { 616 createMethodCode(output,lineNumbers,adder,isInterface); 617 } 618 619 Method remover = role.getRemover(); 620 if (remover==null) { 621 createRemover(output,roleGen,type,primaryKey); 622 } else { 623 createMethodCode(output,lineNumbers,remover,isInterface); 624 } 625 626 Method clearer = role.getClearer(); 627 if (clearer==null) { 628 createClearer(output,roleGen); 629 } else { 630 createMethodCode(output,lineNumbers,clearer,isInterface); 631 } 632 if (primaryKey!=null) { 633 createIndexGetter(output,role); 634 } 635 } 636 } 637 638 /** 639 * Generate the code for a method 640 * @param output where to write generated code 641 * @param lineNumbers 642 * @param method the method to generate code for 643 * @param isInterface wether the method belongs to an interface 644 */ 645 public static void createMethodCode(LineNumberWriter output, 646 Map lineNumbers, 647 Method method, 648 boolean isInterface) 649 throws IOException 650 { 651 output.write("\n/**\n"); 652 String description = method.getDescription(); 653 if (description!=null) { 654 output.write(description); 655 } 656 Iterator params = method.getParameters().iterator(); 657 while (params.hasNext()) { 658 Parameter param = (Parameter)params.next(); 659 output.write("\n@param "+param.getGenerationName()+" "+ 660 param.getDescription()); 661 } 662 output.write("\n*/\n"); 663 lineNumbers.put(method,new Integer(output.getLines())); 664 //Log.trace("ide.codegen",method.getParent()+"."+method.getGenerationName()+ 665 // " starts at "+output.getLines()); 666 output.write("\n "+method.getModifiers()+" "+ 667 method.getPrototype()); 668 if (method.isAbstract() || isInterface) { 669 output.write(";\n"); 670 } else { 671 output.write(" {"); 672 String body = method.getBody(); 673 if (body!=null) 674 output.write( "\n "+body); 675 output.write("\n }\n"); 676 } 677 } 678 679 /** 680 * Generate java source code for an aspect. 681 * 682 * @param prj the project 683 * @param a the aspect 684 * @param baseDir directory where to put the file 685 * @param ppath java package path of the aspect component 686 */ 687 public static void createAspectCode(Project prj,Aspect a, 688 File baseDir,String ppath) { 689 try { 690 print("generating "+a.getName()); 691 File f = new File(baseDir,a.getGenerationName() + "AC.java"); 692 if (f.exists()) 693 f.delete(); 694 f.getParentFile().mkdirs(); 695 f.createNewFile(); 696 String shortName = a.getGenerationName(); 697 FileWriter fw = new FileWriter(f); 698 writeWarning(fw); 699 fw.write( "\npackage "+ppath+";\n" ); 700 fw.write( "import org.objectweb.jac.core.*;\n" ); 701 fw.write( "import org.objectweb.jac.core.rtti.*;\n" ); 702 fw.write( "import org.objectweb.jac.util.*;\n" ); 703 fw.write( "\npublic class "+shortName+ 704 "AC extends org.objectweb.jac.core.AspectComponent"); 705 fw.write( " {\n" ); 706 fw.write( "\n public "+shortName+"AC() {"); 707 Iterator it = a.getPointcutLinks().iterator(); 708 while(it.hasNext()) { 709 PointcutLink pc = (PointcutLink)it.next(); 710 if(pc.getEnd() instanceof org.objectweb.jac.ide.Class) { 711 fw.write("\n pointcut(\""+ 712 "ALL\",\""+ 713 ((org.objectweb.jac.ide.Class)pc.getEnd()).getGenerationFullName()+"\",\""+ 714 pc.getMethodPCD()+"\","+ 715 "new "+shortName+"Wrapper(this)"+",\""+ 716 pc.getAspectRole()+"\",\""+ 717 pc.getHostPCD()+"\",null);"); 718 } else if (pc.getEnd() instanceof Instance) { 719 fw.write("\n pointcut(\""+ 720 ((Instance)pc.getEnd()).getGenerationName()+"\",\""+ 721 ((org.objectweb.jac.ide.Class)((Instance)pc.getEnd()).getType()).getGenerationName()+"\",\""+ 722 pc.getMethodPCD()+"\","+ 723 "new "+shortName+"Wrapper()"+",\""+ 724 pc.getAspectRole()+"\",\""+ 725 pc.getHostPCD()+"\");"); 726 } 727 } 728 fw.write("\n }"); 729 730 fw.write( "\n public class "+shortName+ 731 "Wrapper extends org.objectweb.jac.core.Wrapper {"); 732 733 fw.write( "\n public "+shortName+"Wrapper(AspectComponent ac) {"); 734 fw.write( "\n super(ac);"); 735 fw.write( "\n }"); 736 737 List ms = a.getMethods(); 738 for (int i=0; i<ms.size(); i++) { 739 Method method = (Method)ms.get(i); 740 fw.write("\n "+method.getModifiers()+" "+method.getPrototype()+" {" ); 741 fw.write("\n "+method.getBody()); 742 fw.write("\n }\n"); 743 } 744 745 List fs = a.getFields(); 746 for ( int i = 0; i < fs.size(); i++ ) { 747 Field field=(Field)fs.get(i); 748 fw.write( "\n " + field.getPrototype()+";\n" ); 749 //createSetter(fw,field); 750 //createGetter(fw,field); 751 } 752 753 /*Vector rs = a.getRelationLinks(); 754 for ( int i = 0; i < rs.size(); i++ ) { 755 RelationLink rel=(RelationLink)rs.get(i); 756 fw.write( "\n " + rel.getPrototype()+";\n" ); 757 createSetter(fw,rel); 758 createGetter(fw,rel); 759 760 if(rel.isMultiple()) { 761 createAdder(fw,rel); 762 createRemover(fw,rel); 763 } } */ 764 765 fw.write("\n }"); 766 fw.write( "}\n" ); 767 fw.close(); 768 //print("generation fullfilled."); 769 } catch( Exception e) { 770 e.printStackTrace(); 771 } 772 } 773 774 /** 775 * Generate getter code for collection 776 * @param output write code to this writer 777 * @param name name of the attribute 778 * @param type type of the attribute 779 * @param className the class name if the field is static (null 780 * otherwise) */ 781 static void createGetter(Writer output, String name, String type, 782 boolean isStatic,String className, 783 boolean isInterface) 784 throws IOException 785 { 786 output.write("\n "+(isInterface?"":"public ")+ 787 (isStatic?"static ":"")+type+" get"+ 788 NamingConventions.capitalize(name)+"()"); 789 if (isInterface) { 790 output.write(";\n"); 791 } else { 792 output.write(" {\n"); 793 output.write(" return "+name+";\n"); 794 output.write(" }\n"); 795 } 796 } 797 798 /** 799 * Generate setter code for collection 800 * @param output write code to this writer 801 * @param name name of the attribute 802 * @param type type of the attribute 803 * @param className the class name if the field is static (null 804 * otherwise) */ 805 static void createSetter(Writer output, String name, String type, 806 boolean isStatic, String className, 807 boolean isInterface) 808 throws IOException 809 { 810 output.write("\n "+(isInterface?"":"public")+ 811 (isStatic?" static":"")+" void "+getSetterName(name)+"("+ 812 type+" value)"); 813 if (isInterface) { 814 output.write(";\n"); 815 } else { 816 output.write(" {\n"); 817 if(className==null) { 818 output.write(" this."+name+"=value;\n"); 819 } else { 820 output.write(" "+className+"."+name+"=value;\n"); 821 } 822 output.write(" }\n"); 823 } 824 } 825 826 /** 827 * Returns the setter's name that corresponds to the given field's 828 * name. */ 829 830 public static String getSetterName(String fieldName) { 831 return "set"+NamingConventions.capitalize(fieldName); 832 } 833 834 /** 835 * Returns the getter's name that corresponds to the given field's 836 * name. */ 837 838 public static String getGetterName(String fieldName) { 839 return "get"+NamingConventions.capitalize(fieldName); 840 } 841 842 /** 843 * Returns the adder's name that corresponds to the given 844 * collection's name. */ 845 846 public static String getAdderName(String fieldName) { 847 String fn = NamingConventions.getNormalizedString(fieldName); 848 fn = Projects.plurals.getSingular(fn); 849 return "add"+fn; 850 } 851 852 /** 853 * Returns the clearer's name that corresponds to the given 854 * collection's name. */ 855 856 public static String getClearerName(String fieldName) { 857 String fn = NamingConventions.getNormalizedString(fieldName); 858 fn = Projects.plurals.getSingular(fn); 859 return "clear"+fn; 860 } 861 862 /** 863 * Returns the remover's name that corresponds to the given 864 * collection's name. */ 865 866 public static String getRemoverName(String fieldName) { 867 String fn = NamingConventions.getNormalizedString(fieldName); 868 fn = Projects.plurals.getSingular(fn); 869 return "remove"+fn; 870 } 871 872 public static String keyWrapper(Typed keyField, String value) { 873 if (keyField.getType().isPrimitive()) { 874 return "new "+Classes.getPrimitiveTypeWrapper(keyField.getType().getName())+"("+value+")"; 875 } else { 876 return value; 877 } 878 } 879 880 /** 881 * Generate adder code for collection 882 * 883 * @param output write code to this writer 884 * @param name name of the collection attribute 885 * @param type type of the collection attribute 886 */ 887 static void createAdder(Writer output, String name, String type, 888 Typed primaryKey) 889 throws IOException 890 { 891 output.write("\n public void "+getAdderName(name)+"("+type+" value) {\n"); 892 if (primaryKey==null) 893 output.write(" "+name+".add(value);\n"); 894 else 895 output.write(" "+name+".put("+ 896 keyWrapper(primaryKey,"value."+getGetterName(primaryKey.getGenerationName())+"()")+ 897 ",value);\n"); 898 output.write(" }\n"); 899 } 900 901 902 /** 903 * Generate getter for indexed collection 904 * 905 * @param output write code to this writer 906 * @param name name of the collection attribute 907 * @param type type of the collection attribute 908 */ 909 static void createIndexGetter(Writer output, RelationRole role) 910 throws IOException 911 { 912 Typed primaryKey = role.getPrimaryKey(); 913 String keyName = primaryKey.getGenerationName(); 914 String returnType = role.getEnd().getGenerationName(); 915 output.write("\n public "+returnType+ 916 " get"+Projects.plurals.getSingular(NamingConventions.getNormalizedString(role.getGenerationName()))+"("+ 917 role.getPrimaryKey().getType().getGenerationName()+" "+ 918 keyName+") {\n"); 919 output.write(" return ("+returnType+")"+role.getGenerationName()+".get("+ 920 keyWrapper(primaryKey,keyName)+ 921 ");\n"); 922 output.write(" }\n"); 923 } 924 925 /** 926 * Generate remover code for collection 927 * @param output write code to this writer 928 * @param name name of the collection attribute 929 * @param type type of the collection attribute 930 */ 931 static void createRemover(Writer output, String name, String type, Typed primaryKey) 932 throws IOException 933 { 934 output.write("\n public void "+getRemoverName(name)+"("+type+" value) {\n"); 935 if (primaryKey==null) { 936 output.write(" "+name+".remove(value);\n"); 937 } else { 938 output.write(" "+name+".remove("+ 939 keyWrapper(primaryKey,"value."+getGetterName(primaryKey.getGenerationName())+"()")+ 940 ");\n"); 941 } 942 output.write(" }\n"); 943 } 944 945 /** 946 * Generate clearer code for collection 947 * 948 * @param output write code to this writer 949 * @param name name of the collection attribute 950 * @param type type of the collection attribute 951 */ 952 static void createClearer(Writer output, String name) 953 throws IOException 954 { 955 String fn = NamingConventions.getNormalizedString(name); 956 output.write("\n public void clear"+ 957 fn+"() {\n"); 958 output.write(" "+name+".clear();\n"); 959 output.write(" }\n"); 960 } 961 962 /** 963 * Build a list of the java files for a project. 964 * 965 * @param project the project 966 * @param baseDir base directory for the files 967 * @param list adds the filenames to this list 968 */ 969 static void createJavaFilesList(Project project, File baseDir, List list) { 970 Iterator it = Projects.types.getEnumeratedTypes().iterator(); 971 while(it.hasNext()) { 972 EnumeratedType enum = (EnumeratedType)it.next(); 973 list.add(new File(baseDir,enum.getPackagePath()+ 974 System.getProperty("file.separator")+ 975 Strings.toUSAscii(enum.getName())+".java").getPath()); 976 } 977 978 979 it = project.getPackages().iterator(); 980 while(it.hasNext()) { 981 Package cur = (Package)it.next(); 982 createJavaFilesList(cur, 983 new File(baseDir,cur.getGenerationName()), 984 list); 985 } 986 } 987 988 /** 989 * Build a list of the java files for a package. 990 * 991 * @param pkg the package 992 * @param baseDir base directory for the files 993 * @param list adds to filenames to this list 994 */ 995 static void createJavaFilesList(Package pkg, File baseDir, List list) { 996 Iterator it = pkg.getSubPackages().iterator(); 997 while(it.hasNext()) { 998 Package cur = (Package)it.next(); 999 createJavaFilesList(cur, 1000 new File(baseDir,cur.getGenerationName()), 1001 list); 1002 } 1003 it = pkg.getClasses().iterator(); 1004 while(it.hasNext()) { 1005 Class cl = (Class)it.next(); 1006 if (cl instanceof Aspect) { 1007 list.add(new File(baseDir,cl.getGenerationName()+"AC.java").getPath()); 1008 } else { 1009 list.add(new File(baseDir,cl.getGenerationName()+".java").getPath()); 1010 } 1011 } 1012 1013 it = pkg.getResources().iterator(); 1014 while(it.hasNext()) { 1015 Attachment res = (Attachment)it.next(); 1016 if ("text/x-java".equals(res.getMimeType())) { 1017 list.add(new File(baseDir,res.getName()).getPath()); 1018 } 1019 } 1020 } 1021 1022 /** 1023 * Build a space separated list of the root packages source 1024 * directories of a project. 1025 * 1026 * @param project the project 1027 * @param baseDir base directory of the project 1028 * @return a String 1029 */ 1030 static String createPackageFilesList(Project project,String baseDir) { 1031 StringBuffer result = 1032 new StringBuffer((baseDir.length()+10)*project.getPackages().size()); 1033 Iterator it = project.getPackages().iterator(); 1034 while(it.hasNext()) { 1035 Package cur = (Package)it.next(); 1036 result.append(baseDir + System.getProperty("file.separator") 1037 + cur.getGenerationName() + " "); 1038 } 1039 return result.toString(); 1040 } 1041 1042 // filename -> Class 1043 static transient Hashtable classFiles = new Hashtable(); 1044 1045 /** 1046 * Get the class corresponding to a filename 1047 */ 1048 static Class filenameToClass(String filename) { 1049 Class cl = null; 1050 if ((cl = (Class)classFiles.get(filename))!=null) { 1051 return cl; 1052 } else { 1053 logger.error("Cannot find Class for filename "+filename); 1054 return null; 1055 } 1056 } 1057 1058 public static Errors generateAndCompileProjectCode(Project project, String baseDir) 1059 throws CannotGenerateException, CannotCompileException, IOException, InterruptedException 1060 { 1061 createProjectCode(project,baseDir); 1062 return compileProjectCode(project); 1063 } 1064 1065 /** 1066 * Run compilation command for a project. 1067 * 1068 * @param project the project to compile 1069 * @return A list of errors that occured during compilation. 1070 */ 1071 public static Errors compileProjectCode(Project project) 1072 throws CannotCompileException, IOException, InterruptedException 1073 { 1074 File baseDir = project.getGenerationPath(); 1075 Vector cmdList = new Vector(); 1076 if (!project.getUseToolsJavac()) 1077 cmdList.add(project.getCompilerCommand().toString()); 1078 String[] options = Strings.split(project.getCompilerOptions()," "); 1079 for (int i=0; i<options.length; i++) { 1080 cmdList.add(options[i]); 1081 } 1082 1083 File classesDir = project.getClassesDir(); 1084 cmdList.add("-d"); 1085 cmdList.add(classesDir.getPath()); 1086 1087 // Force UTF-8 since we generate sources with this encoding 1088 cmdList.add("-encoding"); 1089 cmdList.add("UTF-8"); 1090 1091 String classpathString = null; 1092 Collection classpath = new Vector(); 1093 classpath.addAll(project.getClasspath()); 1094 if (!classpath.contains(baseDir)) { 1095 classpath.add(baseDir); 1096 } 1097 if (!classpath.contains(classesDir)) { 1098 classpath.add(classesDir); 1099 } 1100 1101 String jacRoot = org.objectweb.jac.core.Jac.getJacRoot(); 1102 File jacClasses = new File(jacRoot,"classes"); 1103 if (jacClasses.exists() && !classpath.contains(jacClasses)) { 1104 classpath.add(jacClasses); 1105 } 1106 1107 File jacJar = new File(jacRoot+"jac.jar"); 1108 if (jacJar.exists() && !classpath.contains(jacJar)) { 1109 classpath.add(jacJar); 1110 } 1111 1112 File jacDir = new File(jacRoot,"lib"); 1113 java.io.File jars[] = jacDir.listFiles( 1114 new FilenameFilter() { 1115 public boolean accept(java.io.File file, String name) { 1116 return name.endsWith(".jar"); 1117 } 1118 } 1119 ); 1120 if (jars!=null) 1121 classpath.addAll(Arrays.asList(jars)); 1122 String sep = System.getProperty("file.separator"); 1123 classpath.add(new File(jacRoot+sep+"lib"+sep+"opt","jasperreports.jar")); 1124 1125 classpathString = Strings.createPathString(classpath); 1126 1127 logger.info("Classpath = "+classpathString); 1128 if (classpathString!=null) { 1129 cmdList.add("-classpath"); 1130 cmdList.add(classpathString); 1131 } 1132 1133 createJavaFilesList(project,baseDir,cmdList); 1134 1135 File f = new File(baseDir, "classes"); 1136 if (!f.exists()) 1137 f.mkdir(); 1138 1139 logger.info("CMD = "+cmdList); 1140 print("compiling project "+project.getName()+"..."); 1141 1142 BufferedReader reader = null; 1143 final String[] args = (String[])cmdList.toArray(new String[] {}); 1144 if (project.getUseToolsJavac()) { 1145 PrintStream oldErr = System.err; 1146 ByteArrayOutputStream out = new ByteArrayOutputStream(); 1147 System.setErr(new PrintStream(out)); 1148 int res = Main.compile(args); 1149 System.setErr(oldErr); 1150 reader = new BufferedReader( 1151 new InputStreamReader( 1152 new ByteArrayInputStream(out.toByteArray()))); 1153 } else { 1154 Process comp; 1155 try { 1156 comp = Runtime.getRuntime().exec(args); 1157 } catch (IOException e) { 1158 throw new CannotCompileException( 1159 "Failed to start compilation process, is `"+ 1160 project.getCompilerCommand()+"' in your path?"); 1161 } 1162 reader = new BufferedReader( 1163 new InputStreamReader(comp.getErrorStream())); 1164 logger.debug("waiting for compilation to finish "+comp); 1165 } 1166 1167 Vector errors = new Vector(); 1168 String line; 1169 try { 1170 RE re = new RE("^([^:]+):([0-9]+)"); 1171 RE emptyLineRE = new RE("^[ ]*$"); 1172 while ((line=reader.readLine())!=null) { 1173 //Log.trace("ide.compile",line); 1174 REMatch match; 1175 if ((match=re.getMatch(line))!=null) { 1176 //Log.trace("ide.compile", 1177 // "New ERROR : "+match.toString(1)+":"+match.toString(2)); 1178 errors.add(new Error(match.toString(1), 1179 Integer.parseInt(match.toString(2)), 1180 line, 1181 filenameToClass(match.toString(1)))); 1182 } else if (emptyLineRE.getMatch(line)==null) { 1183 errors.add(new Error(line)); 1184 } 1185 } 1186 } catch (REException e) { 1187 throw new CannotCompileException(e.getMessage()); 1188 } 1189 //Log.trace("ide.compile","Found "+errors.size()+" Errors."); 1190 1191 print("compilation done."); 1192 return errors.isEmpty()?null:new Errors(errors); 1193 } 1194 1195 /** 1196 * Generated javadoc documentation for a project 1197 */ 1198 public static void documentProjectCode(Project project,String baseDir) { 1199 String list = createPackageFilesList(project,baseDir); 1200 File f = new File(project.getGenerationPath(),"doc"); 1201 if (!f.exists()) 1202 f.mkdir(); 1203 String cmd = "javadoc -d "+new File(project.getGenerationPath(),"classes")+" "+list; 1204 //Log.trace("ide.compile","CMD = "+cmd); 1205 // to do... 1206 } 1207 1208 /** 1209 * Print status message. 1210 */ 1211 static void print(String msg) { 1212 org.objectweb.jac.aspects.gui.Actions.showStatus(msg); 1213 } 1214 1215 /** 1216 * Generate the ACC configuration code from the ConfigItems 1217 * @param pack package to generate config for 1218 * @param ac the aspect configuration to generate code for 1219 * @param fw generate code to this writer 1220 * @throws IOException 1221 */ 1222 static void generateConfigItemPackageCode(Package pack, AspectConfiguration ac, 1223 Writer fw) 1224 throws IOException 1225 { 1226 AccGenState state = new AccGenState(fw); 1227 Iterator iteClass = pack.getClasses().iterator(); 1228 //Iterate the Classes in the package 1229 while (iteClass.hasNext()) { 1230 Class c = (Class)iteClass.next(); 1231 1232 //iterate the config of the Class 1233 Iterator iteClassConfig = c.getConfigItems().iterator(); 1234 while (iteClassConfig.hasNext()) { 1235 ConfigItem configItem = (ConfigItem)iteClassConfig.next(); 1236 if (configItem.getAspectConfiguration()==ac){ 1237 state.openClass(c); 1238 state.write(translateParam(configItem)); 1239 } 1240 } 1241 //End of the iteration on the class ConfigItem 1242 1243 //iterate the class field 1244 Iterator iteField = c.getFields().iterator(); 1245 while (iteField.hasNext()) { 1246 Field field = (Field)iteField.next(); 1247 //Iteratate the ConfigItem 1248 Iterator iteFieldConfig = field.getConfigItems().iterator(); 1249 while (iteFieldConfig.hasNext()) { 1250 ConfigItem configItem = (ConfigItem)iteFieldConfig.next(); 1251 if (configItem.getAspectConfiguration()==ac){ 1252 state.openField(c,field); 1253 state.write(translateParam(configItem)); 1254 } 1255 } 1256 state.closeMember(); 1257 } 1258 //end of the ConfigItem of the field Class 1259 1260 //iterate the Class Method 1261 Iterator iteMethod = c.getMethods().iterator(); 1262 while (iteMethod.hasNext()) { 1263 Method method = (Method)iteMethod.next(); 1264 //Iteratate the ConfigItem 1265 Iterator iteMethodConfig = method.getConfigItems().iterator(); 1266 while (iteMethodConfig.hasNext()) { 1267 ConfigItem configItem = (ConfigItem)iteMethodConfig.next(); 1268 if (configItem.getAspectConfiguration()==ac){ 1269 state.openMethod(c,method); 1270 state.write(translateParam(configItem)); 1271 } 1272 } 1273 state.closeMember(); 1274 } 1275 //End of the class Method Iteration 1276 1277 //iterate the links between class 1278 /* Not really the Relation Links 1279 Iterator iteLinks=c.getRelationLinks().iterator(); 1280 while(iteLinks.hasNext()){ 1281 RelationLink link=(RelationLink)iteLinks.next(); 1282 Iterator iteLinkConfig=link.getConfigItems().iterator(); 1283 fw.write(" attribute "+link.getGenerationName()+" {\n"); 1284 while(iteLinkConfig.hasNext()){ 1285 ConfigItem item=(ConfigItem)iteLinkConfig.next(); 1286 if (item.getAspectConfiguration()==ac){ 1287 fw.write(" "+translateParam(configItem)); 1288 } 1289 } 1290 fw.write(" }\n"); 1291 } 1292 */ 1293 //end of the Class links iteration 1294 state.closeClass(); 1295 1296 } 1297 1298 //Iterate the sub package 1299 Iterator itePackage = pack.getSubPackages().iterator(); 1300 while (itePackage.hasNext()) { 1301 Package apack = (Package)itePackage.next(); 1302 generateConfigItemPackageCode(apack, ac, fw); 1303 } 1304 } 1305 1306 /** 1307 * Return a string representing the call of method on ModelElement 1308 * element with param param 1309 * @param config the configItem of method 1310 * @return a valid string that the ACCParser will understand */ 1311 public final static String translateParam(ConfigItem config){ 1312 MethodItem method=config.getMethod(); 1313 if (method==null || "".equals(method.getName())) 1314 return ""; 1315 StringBuffer result=new StringBuffer(); 1316 result.append(method.getName()+" "); 1317 Iterator params = config.getParam().iterator(); 1318 while (params.hasNext()) { 1319 String s = (String)params.next(); 1320 //todo if s contain " or keycode we should add/replace some \" 1321 int posBefore = 0, posAfter = 0; 1322 result.append("\""); 1323 while (posBefore!=-1){ 1324 posAfter=s.indexOf('\"',posBefore); 1325 if (posAfter==-1){ 1326 result.append(s.substring(posBefore)); 1327 posBefore = -1; 1328 }else{ 1329 result.append(s.substring(posBefore,posAfter)+"\\\""); 1330 if (posAfter==s.length()-1){ 1331 posBefore = -1; 1332 }else{ 1333 posBefore = posAfter+1; 1334 } 1335 } 1336 } 1337 result.append("\" "); 1338 } 1339 result.append(";\n"); 1340 return result.toString(); 1341 } 1342 1343 /** 1344 * Write the full names of the items of a collection, separated by 1345 * a string. 1346 * @param out where to write 1347 * @param items a collection of ModelElements 1348 * @param separator use this string as a separator 1349 */ 1350 public static void joinFullNames(Writer out, Collection items, String separator) 1351 throws IOException 1352 { 1353 Iterator it = items.iterator(); 1354 while (it.hasNext()) { 1355 out.write(((ModelElement)it.next()).getGenerationFullName()); 1356 if (it.hasNext()) 1357 out.write(separator); 1358 } 1359 } 1360 1361 // Projects mixin methods 1362 1363 public static void generateCode(Projects projects) throws Exception { 1364 Iterator it = projects.getProjects().iterator(); 1365 while (it.hasNext()) { 1366 Project p = (Project)it.next(); 1367 generateCode(p); 1368 } 1369 } 1370 1371 public static Errors compile(Projects projects) throws Exception { 1372 Iterator it = projects.getProjects().iterator(); 1373 while (it.hasNext()) { 1374 Project p = (Project)it.next(); 1375 Errors errors = null; 1376 errors = compile(p); 1377 if (errors!=null) { 1378 return errors; 1379 } 1380 } 1381 return null; 1382 } 1383 1384 public static Errors generateAndCompile(Projects projects) throws Exception { 1385 Iterator it = projects.getProjects().iterator(); 1386 while (it.hasNext()) { 1387 Project p = (Project)it.next(); 1388 Errors errors = null; 1389 errors = generateAndCompile(p); 1390 if (errors!=null) { 1391 return errors; 1392 } 1393 } 1394 return null; 1395 } 1396 1397 // Package mixin methods 1398 1399 public static void generateCode(Package pkg) throws Exception { 1400 Project project = pkg.getProject(); 1401 project.checkGenerationPath(); 1402 createPackageCode( 1403 project, 1404 pkg, 1405 new File(project.getGenerationPath().getPath(),pkg.getPath()), 1406 pkg.getPPath()); 1407 } 1408 1409 // Class mixin methods 1410 1411 public static void generateCode(Class cl) throws Exception { 1412 Package pkg = cl.getContainer(); 1413 Project project = pkg.getProject(); 1414 project.checkGenerationPath(); 1415 createClassCode( 1416 project, 1417 cl, 1418 new File(project.getGenerationPath().getPath(),pkg.getPath()), 1419 pkg.getPPath()); 1420 } 1421 1422 // Project mixin methods 1423 1424 public static void generateCode(Project project) throws Exception { 1425 File generationPath = project.getGenerationPath(); 1426 if (generationPath!=null) { 1427 createProjectCode(project,generationPath.getPath()); 1428 } else { 1429 throw new CannotGenerateException( 1430 "Project \""+project.getName()+"\" does not have a generation path"); 1431 } 1432 } 1433 1434 public static void generateJavaCode(Project project) throws Exception { 1435 File generationPath = project.getGenerationPath(); 1436 if (generationPath!=null) { 1437 createJavaCode(project,generationPath.getPath()); 1438 } else { 1439 throw new CannotGenerateException( 1440 "Project \""+project.getName()+"\" does not have a generation path"); 1441 } 1442 } 1443 1444 public static Errors compile(Project project) 1445 throws CannotCompileException, IOException, InterruptedException 1446 { 1447 File generationPath = project.getGenerationPath(); 1448 if (generationPath!=null) { 1449 return compileProjectCode(project); 1450 } else { 1451 throw new CannotCompileException( 1452 "Project \""+project.getName()+"\" does not have a generation path"); 1453 } 1454 } 1455 1456 public static Errors generateAndCompile(Project project) 1457 throws CannotGenerateException, CannotCompileException, 1458 IOException, InterruptedException, Exception 1459 { 1460 generateJavaCode(project); 1461 return compile(project); 1462 } 1463 1464 1465 /** 1466 * Creates a JAR file containing all the .class files 1467 */ 1468 public static void createJAR(Project project) throws IOException { 1469 createManifest(project); 1470 File generationPath = project.getGenerationPath(); 1471 JarOutputStream out = 1472 new JarOutputStream( 1473 new FileOutputStream( 1474 new File( 1475 generationPath, 1476 project.getGenerationName()+".jar")), 1477 new Manifest( 1478 new FileInputStream( 1479 new File(project.getManifestDir(), "MANIFEST.MF" ))) 1480 ); 1481 1482 // Add class files 1483 File classesDir = project.getClassesDir(); 1484 Iterator it = 1485 project.getClassesDir().listFilesRecursively( 1486 new FilenameFilter() { 1487 public boolean accept(java.io.File file, String name) { 1488 return name.endsWith(".class"); 1489 } 1490 } 1491 ).iterator(); 1492 while (it.hasNext()) { 1493 File classFile = (File)it.next(); 1494 JarEntry entry = new JarEntry(classFile.getRelativePath(classesDir).replace('\\','/')); 1495 out.putNextEntry(entry); 1496 FileInputStream input = new FileInputStream(classFile); 1497 Streams.copy(input,out); 1498 out.closeEntry(); 1499 } 1500 1501 // Add .acc and .jac files 1502 it = project.getApplications().iterator(); 1503 while (it.hasNext()) { 1504 Application application = (Application)it.next(); 1505 Iterator j = application.getAspectConfigurations().iterator(); 1506 File appDir = new File(generationPath,application.getGenerationName()); 1507 while (j.hasNext()) { 1508 AspectConfiguration ac = (AspectConfiguration)j.next(); 1509 File accFile = new File(appDir,ac.getGenerationName()+".acc"); 1510 JarEntry entry = 1511 new JarEntry( 1512 accFile.getRelativePath(generationPath).replace('\\','/')); 1513 out.putNextEntry(entry); 1514 FileInputStream input = new FileInputStream(accFile); 1515 Streams.copy(input,out); 1516 out.closeEntry(); 1517 } 1518 File jacFile = application.getJacFile(); 1519 JarEntry entry = new JarEntry(jacFile.getRelativePath(generationPath)); 1520 out.putNextEntry(entry); 1521 FileInputStream input = new FileInputStream(jacFile); 1522 Streams.copy(input,out); 1523 out.closeEntry(); 1524 } 1525 1526 // Add external files 1527 it = project.getExternalFiles().entrySet().iterator(); 1528 while (it.hasNext()) { 1529 Map.Entry entry = (Map.Entry)it.next(); 1530 JarEntry jarEntry = new JarEntry((String)entry.getKey()); 1531 out.putNextEntry(jarEntry); 1532 FileInputStream input = new FileInputStream((File)entry.getValue()); 1533 Streams.copy(input,out); 1534 out.closeEntry(); 1535 } 1536 1537 // Add resources 1538 it = project.getAllResources().entrySet().iterator(); 1539 while (it.hasNext()) { 1540 Map.Entry entry = (Map.Entry)it.next(); 1541 Package pkg = (Package)entry.getKey(); 1542 Attachment res = (Attachment)entry.getValue(); 1543 JarEntry jarEntry = 1544 new JarEntry( 1545 pkg.getGenerationName()+'/'+res.getName()); 1546 out.putNextEntry(jarEntry); 1547 ByteArrayInputStream input = new ByteArrayInputStream(res.getData()); 1548 Streams.copy(input,out); 1549 out.closeEntry(); 1550 } 1551 out.close(); 1552 } 1553 1554 public static void createManifest(Project project) throws IOException { 1555 File file = project.getManifestDir(); 1556 file.mkdir(); 1557 if (!file.exists()) 1558 new IOException("Could not create META-INF directory"); 1559 1560 FileWriter out = 1561 new FileWriter(new File(project.getManifestDir(), "MANIFEST.MF")); 1562 out.write("Manifest-Version: 1.0\n\n\n\n"); 1563 1564 // Add class files 1565 File classesDir = project.getClassesDir(); 1566 Iterator it = 1567 project.getClassesDir().listFilesRecursively( 1568 new FilenameFilter() { 1569 public boolean accept(java.io.File file, String name) { 1570 return name.endsWith(".class"); 1571 } 1572 } 1573 ).iterator(); 1574 while (it.hasNext()) { 1575 File classFile = (File)it.next(); 1576 out.write("Name: "); 1577 out.write(classFile.getRelativePath(classesDir).replace('\\','/') ); 1578 out.write("\nJava-Bean: True\n\n"); 1579 } 1580 1581 out.close(); 1582 } 1583 1584 // AspectConfiguration mixin methods 1585 1586 public static void generateCode(AspectConfiguration ac) throws Exception { 1587 Project project = ac.getApplication().getProject(); 1588 project.checkGenerationPath(); 1589 CodeGeneration.createACFile( 1590 project,ac, 1591 new File(project.getGenerationPath().getPath(),ac.getApplication().getGenerationName())); 1592 } 1593 1594 public static void generateAndReload(AspectConfiguration ac) throws Throwable { 1595 generateCode(ac); 1596 ac.reload(); 1597 } 1598 }