KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > ide > CodeGeneration


1 /*
2   Copyright (C) 2002-2003 Renaud Pawlak <renaud@aopsys.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program 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
12   GNU 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 program; 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.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     /**
64      * Generate code for all the classes and aspects of a project.
65      *
66      * @param project the project
67      * @param baseDir base directory where to put generated files
68      */

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     /**
82      * Generate java sources for a project
83      * @param project a project
84      * @param baseDir directory where to generate files
85      */

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     /**
104      * Generate java sources for an enumerated type.
105      *
106      * @param enum an enumerated type
107      * @param dir directory where to generate the file
108      */

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                 // remove unwanted characters such as '.'
128
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     /**
145      * Generate code for an application (<code>Run</code> and aspect
146      * configurations)
147      *
148      * @param prj the project
149      * @param app the application
150      * @param baseDir the base directory where to put the generated files
151      */

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             //createDefaultACFile(prj,ac,baseDir);
162
}
163         createJACFile(prj,app,baseDir);
164     }
165
166     /**
167      * Generate a warning that the file was automatically generated.
168      *
169      * @param writer writer where to write the warning
170      */

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     // aspect name -> AspectPlugin
183
static transient Map aspectPlugins = new Hashtable();
184     static {
185         aspectPlugins.put("rtti", new RttiPlugin());
186         //aspectPlugins.put("integrity", new IntegrityPlugin());
187
aspectPlugins.put("gui", new GuiPlugin());
188         aspectPlugins.put("persistence", new PersistencePlugin());
189     }
190
191     /**
192      * Generate aspect configuration code for an aspect of a project.
193      *
194      * @param project the project
195      * @param ac the aspect configuration
196      * @param dir directory where to put the file
197      */

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             // Automatically generated config code
209
if (aspectPlugins.containsKey(ac.getName())) {
210                 AspectPlugin plugin =
211                     (AspectPlugin)aspectPlugins.get(ac.getName());
212                 plugin.genConfig(fw,project);
213             }
214
215             // common default configurations for all classes
216
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             //Create Acc ConfigurationCode from the ConfigItem
229
//First creating code from the Project
230
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             //Iterate on each package of the project
241
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             // main config
249
fw.write(ac.getConfigurationCode());
250             fw.close();
251         } catch(Exception e) {
252             e.printStackTrace();
253         }
254     }
255
256     /**
257      * Build a list of paths for all the classes of a project.
258      *
259      * @param project the project
260      * @return a collection of Strings which are the paths of the
261      * source files of the classes
262      * @see createClassesList(Package,String)
263      */

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     /**
275      * Build a list of paths for all the classes of a package and its
276      * subpackages.
277      *
278      * @param package the package
279      * @return a collection of Strings which are the paths of the
280      * source files of the classes
281      */

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     /**
298      * Generate the descriptor of an application (the .jac file).
299      *
300      * @param prj the project
301      * @param app the applicatino
302      * @param baseDir directory where to put the <code>.jac</code> file
303      */

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     /**
376      * Generate code for the classes of a package and its subpackages.
377      *
378      * @param prj the project
379      * @param pkg the package
380      * @param baseDir directory where to put the files of the package
381      * @param ppath java package path (<code>myapp.mypackage</code> for instance)
382      */

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     // Class -> ( Method -> (Integer)lineNumber )
422
static transient Hashtable classesLineNumbers = new Hashtable();
423
424     /**
425      * Returns a Map giving the line number of methods in the generated
426      * java source file.
427      */

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     /**
438      * Generate the java source code of a class.
439      *
440      * @param prj the project
441      * @param c the class
442      * @param baseDir directory where to put the generated file
443      * @param ppath java package path of the class
444      */

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             // Automatic imports for field types
465
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             // Imports of the class
477
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             //print("generation fullfilled.");
530
} catch( Exception e) {
531             e.printStackTrace();
532         }
533     }
534
535     /**
536      * Generate the code for a field, its getter and its setter
537      *
538      * @param output where to write generated code
539      * @param lineNumbers line numbers information will be stored in this map
540      * @param field the field to generate code for
541      * @param isInterface wether the field belongs to an interface
542      */

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     /**
653      * Generate the code for a method
654      * @param output where to write generated code
655      * @param lineNumbers
656      * @param method the method to generate code for
657      * @param isInterface wether the method belongs to an interface
658      */

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         //Log.trace("ide.codegen",method.getParent()+"."+method.getGenerationName()+
679
// " starts at "+output.getLines());
680
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     /**
694      * Generate java source code for an aspect.
695      *
696      * @param prj the project
697      * @param a the aspect
698      * @param baseDir directory where to put the file
699      * @param ppath java package path of the aspect component
700      */

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()+"\","+
737                              "new "+shortName+"Wrapper()"+",\""+
738                              pc.getAspectRole()+"\",\""+
739                              pc.getHostPCD()+"\");");
740                 }
741             }
742             fw.write("\n }");
743
744             fw.write( "\n public class "+shortName+
745                       "Wrapper extends org.objectweb.jac.core.Wrapper {");
746
747             fw.write( "\n public "+shortName+"Wrapper(AspectComponent ac) {");
748             fw.write( "\n super(ac);");
749             fw.write( "\n }");
750
751             List ms = a.getMethods();
752             for (int i=0; i<ms.size(); i++) {
753                 Method method = (Method)ms.get(i);
754                 fw.write("\n "+method.getModifiers()+" "+method.getPrototype()+" {" );
755                 fw.write("\n "+method.getBody());
756                 fw.write("\n }\n");
757             }
758
759             List fs = a.getFields();
760             for ( int i = 0; i < fs.size(); i++ ) {
761                 Field field=(Field)fs.get(i);
762                 fw.write( "\n " + field.getPrototype()+";\n" );
763                 //createSetter(fw,field);
764
//createGetter(fw,field);
765
}
766
767             /*Vector rs = a.getRelationLinks();
768               for ( int i = 0; i < rs.size(); i++ ) {
769               RelationLink rel=(RelationLink)rs.get(i);
770               fw.write( "\n " + rel.getPrototype()+";\n" );
771               createSetter(fw,rel);
772               createGetter(fw,rel);
773
774               if(rel.isMultiple()) {
775               createAdder(fw,rel);
776               createRemover(fw,rel);
777               } } */

778
779             fw.write("\n }");
780             fw.write( "}\n" );
781             fw.close();
782             //print("generation fullfilled.");
783
} catch( Exception e) {
784             e.printStackTrace();
785         }
786     }
787
788     /**
789      * Generate getter code for collection
790      * @param output write code to this writer
791      * @param name name of the attribute
792      * @param type type of the attribute
793      * @param className the class name if the field is static (null
794      * otherwise) */

795     static void createGetter(Writer output, String name, String type,
796                              boolean isStatic,String className,
797                              boolean isInterface)
798         throws IOException
799     {
800         output.write("\n "+(isInterface?"":"public ")+
801                      (isStatic?"static ":"")+type+" get"+
802                      NamingConventions.capitalize(name)+"()");
803         if (isInterface) {
804             output.write(";\n");
805         } else {
806             output.write(" {\n");
807             output.write(" return "+name+";\n");
808             output.write(" }\n");
809         }
810     }
811
812     /**
813      * Generate setter code for collection
814      * @param output write code to this writer
815      * @param name name of the attribute
816      * @param type type of the attribute
817      * @param className the class name if the field is static (null
818      * otherwise) */

819     static void createSetter(Writer output, String name, String type,
820                              boolean isStatic, String className,
821                              boolean isInterface)
822         throws IOException
823     {
824         output.write("\n "+(isInterface?"":"public")+
825                      (isStatic?" static":"")+" void "+getSetterName(name)+"("+
826                      type+" value)");
827         if (isInterface) {
828             output.write(";\n");
829         } else {
830             output.write(" {\n");
831             if(className==null) {
832                 output.write(" this."+name+"=value;\n");
833             } else {
834                 output.write(" "+className+"."+name+"=value;\n");
835             }
836             output.write(" }\n");
837         }
838     }
839
840     /**
841      * Returns the setter's name that corresponds to the given field's
842      * name. */

843
844     public static String getSetterName(String fieldName) {
845         return "set"+NamingConventions.capitalize(fieldName);
846     }
847
848     /**
849      * Returns the getter's name that corresponds to the given field's
850      * name. */

851
852     public static String getGetterName(String fieldName) {
853         return "get"+NamingConventions.capitalize(fieldName);
854     }
855
856     /**
857      * Returns the adder's name that corresponds to the given
858      * collection's name. */

859
860     public static String getAdderName(String fieldName) {
861         String fn = NamingConventions.getNormalizedString(fieldName);
862         fn = Projects.plurals.getSingular(fn);
863         return "add"+fn;
864     }
865
866     /**
867      * Returns the clearer's name that corresponds to the given
868      * collection's name. */

869
870     public static String getClearerName(String fieldName) {
871         String fn = NamingConventions.getNormalizedString(fieldName);
872         fn = Projects.plurals.getSingular(fn);
873         return "clear"+fn;
874     }
875
876     /**
877      * Returns the remover's name that corresponds to the given
878      * collection's name. */

879
880     public static String getRemoverName(String fieldName) {
881         String fn = NamingConventions.getNormalizedString(fieldName);
882         fn = Projects.plurals.getSingular(fn);
883         return "remove"+fn;
884     }
885
886     public static String keyWrapper(Typed keyField, String value) {
887         if (keyField.getType().isPrimitive()) {
888             return "new "+Classes.getPrimitiveTypeWrapper(keyField.getType().getName())+"("+value+")";
889         } else {
890             return value;
891         }
892     }
893
894     /**
895      * Generate adder code for collection
896      *
897      * @param output write code to this writer
898      * @param name name of the collection attribute
899      * @param type type of the collection attribute
900      */

901     static void createAdder(Writer output, String name, String type,
902                             Typed primaryKey)
903         throws IOException
904     {
905         output.write("\n public void "+getAdderName(name)+"("+type+" value) {\n");
906         if (primaryKey==null)
907             output.write(" "+name+".add(value);\n");
908         else
909             output.write(" "+name+".put("+
910                          keyWrapper(primaryKey,"value."+getGetterName(primaryKey.getGenerationName())+"()")+
911                          ",value);\n");
912         output.write(" }\n");
913     }
914
915
916     /**
917      * Generate getter for indexed collection
918      *
919      * @param output write code to this writer
920      * @param name name of the collection attribute
921      * @param type type of the collection attribute
922      */

923     static void createIndexGetter(Writer output, RelationRole role)
924         throws IOException
925     {
926         Typed primaryKey = role.getPrimaryKey();
927         String keyName = primaryKey.getGenerationName();
928         String returnType = role.getEnd().getGenerationName();
929         output.write("\n public "+returnType+
930                      " get"+Projects.plurals.getSingular(NamingConventions.getNormalizedString(role.getGenerationName()))+"("+
931                      role.getPrimaryKey().getType().getGenerationName()+" "+
932                      keyName+") {\n");
933         output.write(" return ("+returnType+")"+role.getGenerationName()+".get("+
934                      keyWrapper(primaryKey,keyName)+
935                      ");\n");
936         output.write(" }\n");
937     }
938
939     /**
940      * Generate remover code for collection
941      * @param output write code to this writer
942      * @param name name of the collection attribute
943      * @param type type of the collection attribute
944      */

945     static void createRemover(Writer output, String name, String type, Typed primaryKey)
946         throws IOException
947     {
948         output.write("\n public void "+getRemoverName(name)+"("+type+" value) {\n");
949         if (primaryKey==null) {
950             output.write(" "+name+".remove(value);\n");
951         } else {
952             output.write(" "+name+".remove("+
953                          keyWrapper(primaryKey,"value."+getGetterName(primaryKey.getGenerationName())+"()")+
954                          ");\n");
955         }
956         output.write(" }\n");
957     }
958
959     /**
960      * Generate clearer code for collection
961      *
962      * @param output write code to this writer
963      * @param name name of the collection attribute
964      * @param type type of the collection attribute
965      */

966     static void createClearer(Writer output, String name)
967         throws IOException
968     {
969         String fn = NamingConventions.getNormalizedString(name);
970         output.write("\n public void clear"+
971                      fn+"() {\n");
972         output.write(" "+name+".clear();\n");
973         output.write(" }\n");
974     }
975
976     /**
977      * Build a list of the java files for a project.
978      *
979      * @param project the project
980      * @param baseDir base directory for the files
981      * @param list adds the filenames to this list
982      */

983     static void createJavaFilesList(Project project, File baseDir, List list) {
984         Iterator it = Projects.types.getEnumeratedTypes().iterator();
985         while(it.hasNext()) {
986             EnumeratedType enum = (EnumeratedType)it.next();
987             list.add(new File(baseDir,enum.getPackagePath()+
988                               System.getProperty("file.separator")+
989                               Strings.toUSAscii(enum.getName())+".java").getPath());
990         }
991
992
993         it = project.getPackages().iterator();
994         while(it.hasNext()) {
995             Package cur = (Package)it.next();
996             createJavaFilesList(cur,
997                                 new File(baseDir,cur.getGenerationName()),
998                                 list);
999         }
1000    }
1001
1002    /**
1003     * Build a list of the java files for a package.
1004     *
1005     * @param pkg the package
1006     * @param baseDir base directory for the files
1007     * @param list adds to filenames to this list
1008     */

1009    static void createJavaFilesList(Package pkg, File baseDir, List list) {
1010        Iterator it = pkg.getSubPackages().iterator();
1011        while(it.hasNext()) {
1012            Package cur = (Package)it.next();
1013            createJavaFilesList(cur,
1014                                new File(baseDir,cur.getGenerationName()),
1015                                list);
1016        }
1017        it = pkg.getClasses().iterator();
1018        while(it.hasNext()) {
1019            Class cl = (Class)it.next();
1020            if (cl instanceof Aspect) {
1021                list.add(new File(baseDir,cl.getGenerationName()+"AC.java").getPath());
1022            } else {
1023                list.add(new File(baseDir,cl.getGenerationName()+".java").getPath());
1024            }
1025        }
1026
1027        it = pkg.getResources().iterator();
1028        while(it.hasNext()) {
1029            Attachment res = (Attachment)it.next();
1030            if ("text/x-java".equals(res.getMimeType())) {
1031                list.add(new File(baseDir,res.getName()).getPath());
1032            }
1033        }
1034    }
1035
1036    /**
1037     * Build a space separated list of the root packages source
1038     * directories of a project.
1039     *
1040     * @param project the project
1041     * @param baseDir base directory of the project
1042     * @return a String
1043     */

1044    static String createPackageFilesList(Project project,String baseDir) {
1045        StringBuffer result =
1046            new StringBuffer((baseDir.length()+10)*project.getPackages().size());
1047        Iterator it = project.getPackages().iterator();
1048        while(it.hasNext()) {
1049            Package cur = (Package)it.next();
1050            result.append(baseDir + System.getProperty("file.separator")
1051                          + cur.getGenerationName() + " ");
1052        }
1053        return result.toString();
1054    }
1055
1056    // filename -> Class
1057
static transient Hashtable classFiles = new Hashtable();
1058
1059    /**
1060     * Get the class corresponding to a filename
1061     */

1062    static Class filenameToClass(String filename) {
1063        Class cl = null;
1064        if ((cl = (Class)classFiles.get(filename))!=null) {
1065            return cl;
1066        } else {
1067            logger.error("Cannot find Class for filename "+filename);
1068            return null;
1069        }
1070    }
1071
1072    public static Errors generateAndCompileProjectCode(Project project, String baseDir)
1073        throws CannotGenerateException, CannotCompileException, IOException, InterruptedException
1074    {
1075        createProjectCode(project,baseDir);
1076        return compileProjectCode(project);
1077    }
1078
1079    /**
1080     * Run compilation command for a project.
1081     *
1082     * @param project the project to compile
1083     * @return A list of errors that occured during compilation.
1084     */

1085    public static Errors compileProjectCode(Project project)
1086        throws CannotCompileException, IOException, InterruptedException
1087    {
1088        File baseDir = project.getGenerationPath();
1089        Vector cmdList = new Vector();
1090        if (!project.getUseToolsJavac())
1091            cmdList.add(project.getCompilerCommand().toString());
1092        String[] options = Strings.split(project.getCompilerOptions()," ");
1093        for (int i=0; i<options.length; i++) {
1094            cmdList.add(options[i]);
1095        }
1096
1097        File classesDir = project.getClassesDir();
1098        cmdList.add("-d");
1099        cmdList.add(classesDir.getPath());
1100
1101        // Force UTF-8 since we generate sources with this encoding
1102
cmdList.add("-encoding");
1103        cmdList.add("UTF-8");
1104
1105        String classpathString = null;
1106        Collection classpath = new Vector();
1107        classpath.addAll(project.getClasspath());
1108        if (!classpath.contains(baseDir)) {
1109            classpath.add(baseDir);
1110        }
1111        if (!classpath.contains(classesDir)) {
1112            classpath.add(classesDir);
1113        }
1114
1115        String jacRoot = org.objectweb.jac.core.Jac.getJacRoot();
1116        File jacClasses = new File(jacRoot,"classes");
1117        if (jacClasses.exists() && !classpath.contains(jacClasses)) {
1118            classpath.add(jacClasses);
1119        }
1120
1121        File jacJar = new File(jacRoot+"jac.jar");
1122        if (jacJar.exists() && !classpath.contains(jacJar)) {
1123            classpath.add(jacJar);
1124        }
1125
1126        File jacDir = new File(jacRoot,"lib");
1127        java.io.File jars[] = jacDir.listFiles(
1128            new FilenameFilter() {
1129                    public boolean accept(java.io.File file, String name) {
1130                        return name.endsWith(".jar");
1131                    }
1132                }
1133        );
1134        if (jars!=null)
1135            classpath.addAll(Arrays.asList(jars));
1136        String sep = System.getProperty("file.separator");
1137        classpath.add(new File(jacRoot+sep+"lib"+sep+"opt","jasperreports.jar"));
1138
1139        classpathString = Strings.createPathString(classpath);
1140
1141        logger.info("Classpath = "+classpathString);
1142        if (classpathString!=null) {
1143            cmdList.add("-classpath");
1144            cmdList.add(classpathString);
1145        }
1146
1147        createJavaFilesList(project,baseDir,cmdList);
1148
1149        File f = new File(baseDir, "classes");
1150        if (!f.exists())
1151            f.mkdir();
1152
1153        logger.info("CMD = "+cmdList);
1154        print("compiling project "+project.getName()+"...");
1155
1156        BufferedReader reader = null;
1157        final String[] args = (String[])cmdList.toArray(new String[] {});
1158        if (project.getUseToolsJavac()) {
1159            PrintStream oldErr = System.err;
1160            ByteArrayOutputStream out = new ByteArrayOutputStream();
1161            System.setErr(new PrintStream(out));
1162            int res = Main.compile(args);
1163            System.setErr(oldErr);
1164            reader = new BufferedReader(
1165                new InputStreamReader(
1166                    new ByteArrayInputStream(out.toByteArray())));
1167        } else {
1168            Process comp;
1169            try {
1170                comp = Runtime.getRuntime().exec(args);
1171            } catch (IOException e) {
1172                throw new CannotCompileException(
1173                    "Failed to start compilation process, is `"+
1174                    project.getCompilerCommand()+"' in your path?");
1175            }
1176            reader = new BufferedReader(
1177                new InputStreamReader(comp.getErrorStream()));
1178            logger.debug("waiting for compilation to finish "+comp);
1179        }
1180
1181        Vector errors = new Vector();
1182        String line;
1183        try {
1184            RE re = new RE("^([^:]+):([0-9]+)");
1185            RE emptyLineRE = new RE("^[ ]*$");
1186            while ((line=reader.readLine())!=null) {
1187                //Log.trace("ide.compile",line);
1188
REMatch match;
1189                if ((match=re.getMatch(line))!=null) {
1190                    //Log.trace("ide.compile",
1191
// "New ERROR : "+match.toString(1)+":"+match.toString(2));
1192
errors.add(new Error(match.toString(1),
1193                                         Integer.parseInt(match.toString(2)),
1194                                         line,
1195                                         filenameToClass(match.toString(1))));
1196                } else if (emptyLineRE.getMatch(line)==null) {
1197                    errors.add(new Error(line));
1198                }
1199            }
1200        } catch (REException e) {
1201            throw new CannotCompileException(e.getMessage());
1202        }
1203        //Log.trace("ide.compile","Found "+errors.size()+" Errors.");
1204

1205        print("compilation done.");
1206        return errors.isEmpty()?null:new Errors(errors);
1207    }
1208
1209    /**
1210     * Generated javadoc documentation for a project
1211     */

1212    public static void documentProjectCode(Project project,String baseDir) {
1213        String list = createPackageFilesList(project,baseDir);
1214        File f = new File(project.getGenerationPath(),"doc");
1215        if (!f.exists())
1216            f.mkdir();
1217        String cmd = "javadoc -d "+new File(project.getGenerationPath(),"classes")+" "+list;
1218        //Log.trace("ide.compile","CMD = "+cmd);
1219
// to do...
1220
}
1221
1222    /**
1223     * Print status message.
1224     */

1225    static void print(String msg) {
1226        org.objectweb.jac.aspects.gui.Actions.showStatus(msg);
1227    }
1228
1229    /**
1230     * Generate the ACC configuration code from the ConfigItems
1231     * @param pack package to generate config for
1232     * @param ac the aspect configuration to generate code for
1233     * @param fw generate code to this writer
1234     * @throws IOException
1235     */

1236    static void generateConfigItemPackageCode(Package pack, AspectConfiguration ac,
1237                                              Writer fw)
1238        throws IOException
1239    {
1240        AccGenState state = new AccGenState(fw);
1241        Iterator iteClass = pack.getClasses().iterator();
1242        //Iterate the Classes in the package
1243
while (iteClass.hasNext()) {
1244            Class c = (Class)iteClass.next();
1245
1246            //iterate the config of the Class
1247
Iterator iteClassConfig = c.getConfigItems().iterator();
1248            while (iteClassConfig.hasNext()) {
1249                ConfigItem configItem = (ConfigItem)iteClassConfig.next();
1250                if (configItem.getAspectConfiguration()==ac){
1251                    state.openClass(c);
1252                    state.write(translateParam(configItem));
1253                }
1254            }
1255            //End of the iteration on the class ConfigItem
1256

1257            //iterate the class field
1258
Iterator iteField = c.getFields().iterator();
1259            while (iteField.hasNext()) {
1260                Field field = (Field)iteField.next();
1261                //Iteratate the ConfigItem
1262
Iterator iteFieldConfig = field.getConfigItems().iterator();
1263                while (iteFieldConfig.hasNext()) {
1264                    ConfigItem configItem = (ConfigItem)iteFieldConfig.next();
1265                    if (configItem.getAspectConfiguration()==ac){
1266                        state.openField(c,field);
1267                        state.write(translateParam(configItem));
1268                    }
1269                }
1270                state.closeMember();
1271            }
1272            //end of the ConfigItem of the field Class
1273

1274            //iterate the Class Method
1275
Iterator iteMethod = c.getMethods().iterator();
1276            while (iteMethod.hasNext()) {
1277                Method method = (Method)iteMethod.next();
1278                //Iteratate the ConfigItem
1279
Iterator iteMethodConfig = method.getConfigItems().iterator();
1280                while (iteMethodConfig.hasNext()) {
1281                    ConfigItem configItem = (ConfigItem)iteMethodConfig.next();
1282                    if (configItem.getAspectConfiguration()==ac){
1283                        state.openMethod(c,method);
1284                        state.write(translateParam(configItem));
1285                    }
1286                }
1287                state.closeMember();
1288            }
1289            //End of the class Method Iteration
1290

1291            //iterate the links between class
1292
/* Not really the Relation Links
1293               Iterator iteLinks=c.getRelationLinks().iterator();
1294               while(iteLinks.hasNext()){
1295               RelationLink link=(RelationLink)iteLinks.next();
1296               Iterator iteLinkConfig=link.getConfigItems().iterator();
1297               fw.write(" attribute "+link.getGenerationName()+" {\n");
1298               while(iteLinkConfig.hasNext()){
1299               ConfigItem item=(ConfigItem)iteLinkConfig.next();
1300               if (item.getAspectConfiguration()==ac){
1301               fw.write(" "+translateParam(configItem));
1302               }
1303               }
1304               fw.write(" }\n");
1305               }
1306            */

1307            //end of the Class links iteration
1308
state.closeClass();
1309
1310        }
1311
1312        //Iterate the sub package
1313
Iterator itePackage = pack.getSubPackages().iterator();
1314        while (itePackage.hasNext()) {
1315            Package apack = (Package)itePackage.next();
1316            generateConfigItemPackageCode(apack, ac, fw);
1317        }
1318    }
1319
1320    /**
1321     * Return a string representing the call of method on ModelElement
1322     * element with param param
1323     * @param config the configItem of method
1324     * @return a valid string that the ACCParser will understand */

1325    public final static String translateParam(ConfigItem config){
1326        MethodItem method=config.getMethod();
1327        if (method==null || "".equals(method.getName()))
1328            return "";
1329        StringBuffer result=new StringBuffer();
1330        result.append(method.getName()+" ");
1331        Iterator params = config.getParam().iterator();
1332        while (params.hasNext()) {
1333            String s = (String)params.next();
1334            //todo if s contain " or keycode we should add/replace some \"
1335
int posBefore = 0, posAfter = 0;
1336            result.append("\"");
1337            while (posBefore!=-1){
1338                posAfter=s.indexOf('\"',posBefore);
1339                if (posAfter==-1){
1340                    result.append(s.substring(posBefore));
1341                    posBefore = -1;
1342                }else{
1343                    result.append(s.substring(posBefore,posAfter)+"\\\"");
1344                    if (posAfter==s.length()-1){
1345                        posBefore = -1;
1346                    }else{
1347                        posBefore = posAfter+1;
1348                    }
1349                }
1350            }
1351            result.append("\" ");
1352        }
1353        result.append(";\n");
1354        return result.toString();
1355    }
1356
1357    /**
1358     * Write the full names of the items of a collection, separated by
1359     * a string.
1360     * @param out where to write
1361     * @param items a collection of ModelElements
1362     * @param separator use this string as a separator
1363     */

1364    public static void joinFullNames(Writer out, Collection items, String separator)
1365        throws IOException
1366    {
1367        Iterator it = items.iterator();
1368        while (it.hasNext()) {
1369            out.write(((ModelElement)it.next()).getGenerationFullName());
1370            if (it.hasNext())
1371                out.write(separator);
1372        }
1373    }
1374
1375    // Projects mixin methods
1376

1377    public static void generateCode(Projects projects) throws Exception {
1378        Iterator it = projects.getProjects().iterator();
1379        while (it.hasNext()) {
1380            Project p = (Project)it.next();
1381            generateCode(p);
1382        }
1383    }
1384
1385    public static Errors compile(Projects projects) throws Exception {
1386        Iterator it = projects.getProjects().iterator();
1387        while (it.hasNext()) {
1388            Project p = (Project)it.next();
1389            Errors errors = null;
1390            errors = compile(p);
1391            if (errors!=null) {
1392                return errors;
1393            }
1394        }
1395        return null;
1396    }
1397
1398    public static Errors generateAndCompile(Projects projects) throws Exception {
1399        Iterator it = projects.getProjects().iterator();
1400        while (it.hasNext()) {
1401            Project p = (Project)it.next();
1402            Errors errors = null;
1403            errors = generateAndCompile(p);
1404            if (errors!=null) {
1405                return errors;
1406            }
1407        }
1408        return null;
1409    }
1410
1411    // Package mixin methods
1412

1413    public static void generateCode(Package pkg) throws Exception {
1414        Project project = pkg.getProject();
1415        project.checkGenerationPath();
1416        createPackageCode(
1417            project,
1418            pkg,
1419            new File(project.getGenerationPath().getPath(),pkg.getPath()),
1420            pkg.getPPath());
1421    }
1422
1423    // Class mixin methods
1424

1425    public static void generateCode(Class cl) throws Exception {
1426        Package pkg = cl.getContainer();
1427        Project project = pkg.getProject();
1428        project.checkGenerationPath();
1429        createClassCode(
1430            project,
1431            cl,
1432            new File(project.getGenerationPath().getPath(),pkg.getPath()),
1433            pkg.getPPath());
1434    }
1435
1436    // Project mixin methods
1437

1438    public static void generateCode(Project project) throws Exception {
1439        File generationPath = project.getGenerationPath();
1440        if (generationPath!=null) {
1441            createProjectCode(project,generationPath.getPath());
1442        } else {
1443            throw new CannotGenerateException(
1444                "Project \""+project.getName()+"\" does not have a generation path");
1445        }
1446    }
1447
1448    public static void generateJavaCode(Project project) throws Exception {
1449        File generationPath = project.getGenerationPath();
1450        if (generationPath!=null) {
1451            createJavaCode(project,generationPath.getPath());
1452        } else {
1453            throw new CannotGenerateException(
1454                "Project \""+project.getName()+"\" does not have a generation path");
1455        }
1456    }
1457
1458    public static Errors compile(Project project)
1459        throws CannotCompileException, IOException, InterruptedException
1460    {
1461        File generationPath = project.getGenerationPath();
1462        if (generationPath!=null) {
1463            return compileProjectCode(project);
1464        } else {
1465            throw new CannotCompileException(
1466                "Project \""+project.getName()+"\" does not have a generation path");
1467        }
1468    }
1469
1470    public static Errors generateAndCompile(Project project)
1471        throws CannotGenerateException, CannotCompileException,
1472               IOException, InterruptedException, Exception
1473    {
1474        generateJavaCode(project);
1475        return compile(project);
1476    }
1477
1478    
1479    /**
1480     * Creates a JAR file containing all the .class files
1481     */

1482    public static void createJAR(Project project) throws IOException {
1483        createManifest(project);
1484        File generationPath = project.getGenerationPath();
1485        JarOutputStream out =
1486            new JarOutputStream(
1487                new FileOutputStream(
1488                    new File(
1489                        generationPath,
1490                        project.getGenerationName()+".jar")),
1491                new Manifest(
1492                    new FileInputStream(
1493                        new File(project.getManifestDir(), "MANIFEST.MF" )))
1494            );
1495
1496        // Add class files
1497
File classesDir = project.getClassesDir();
1498        Iterator it =
1499            project.getClassesDir().listFilesRecursively(
1500                new FilenameFilter() {
1501                        public boolean accept(java.io.File file, String name) {
1502                            return name.endsWith(".class");
1503                        }
1504                    }
1505            ).iterator();
1506        while (it.hasNext()) {
1507            File classFile = (File)it.next();
1508            JarEntry entry = new JarEntry(classFile.getRelativePath(classesDir).replace('\\','/'));
1509            out.putNextEntry(entry);
1510            FileInputStream input = new FileInputStream(classFile);
1511            Streams.copy(input,out);
1512            out.closeEntry();
1513        }
1514        
1515        // Add .acc and .jac files
1516
it = project.getApplications().iterator();
1517        while (it.hasNext()) {
1518            Application application = (Application)it.next();
1519            Iterator j = application.getAspectConfigurations().iterator();
1520            File appDir = new File(generationPath,application.getGenerationName());
1521            while (j.hasNext()) {
1522                AspectConfiguration ac = (AspectConfiguration)j.next();
1523                File accFile = new File(appDir,ac.getGenerationName()+".acc");
1524                JarEntry entry =
1525                    new JarEntry(
1526                        accFile.getRelativePath(generationPath).replace('\\','/'));
1527                out.putNextEntry(entry);
1528                FileInputStream input = new FileInputStream(accFile);
1529                Streams.copy(input,out);
1530                out.closeEntry();
1531            }
1532            File jacFile = application.getJacFile();
1533            JarEntry entry = new JarEntry(jacFile.getRelativePath(generationPath));
1534            out.putNextEntry(entry);
1535            FileInputStream input = new FileInputStream(jacFile);
1536            Streams.copy(input,out);
1537            out.closeEntry();
1538        }
1539
1540        // Add external files
1541
it = project.getExternalFiles().entrySet().iterator();
1542        while (it.hasNext()) {
1543            Map.Entry entry = (Map.Entry)it.next();
1544            JarEntry jarEntry = new JarEntry((String)entry.getKey());
1545            out.putNextEntry(jarEntry);
1546            FileInputStream input = new FileInputStream((File)entry.getValue());
1547            Streams.copy(input,out);
1548            out.closeEntry();
1549        }
1550
1551        // Add resources
1552
it = project.getAllResources().entrySet().iterator();
1553        while (it.hasNext()) {
1554            Map.Entry entry = (Map.Entry)it.next();
1555            Package pkg = (Package)entry.getKey();
1556            Attachment res = (Attachment)entry.getValue();
1557            JarEntry jarEntry =
1558                new JarEntry(
1559                    pkg.getGenerationName()+'/'+res.getName());
1560            out.putNextEntry(jarEntry);
1561            ByteArrayInputStream input = new ByteArrayInputStream(res.getData());
1562            Streams.copy(input,out);
1563            out.closeEntry();
1564        }
1565        out.close();
1566    }
1567
1568    public static void createManifest(Project project) throws IOException {
1569        File file = project.getManifestDir();
1570        file.mkdir();
1571        if (!file.exists())
1572            new IOException("Could not create META-INF directory");
1573            
1574        FileWriter out =
1575                new FileWriter(new File(project.getManifestDir(), "MANIFEST.MF"));
1576        out.write("Manifest-Version: 1.0\n\n\n\n");
1577
1578        // Add class files
1579
File classesDir = project.getClassesDir();
1580        Iterator it =
1581            project.getClassesDir().listFilesRecursively(
1582                new FilenameFilter() {
1583                        public boolean accept(java.io.File file, String name) {
1584                            return name.endsWith(".class");
1585                        }
1586                    }
1587            ).iterator();
1588        while (it.hasNext()) {
1589            File classFile = (File)it.next();
1590            out.write("Name: ");
1591            out.write(classFile.getRelativePath(classesDir).replace('\\','/') );
1592            out.write("\nJava-Bean: True\n\n");
1593        }
1594
1595        out.close();
1596    }
1597
1598    // AspectConfiguration mixin methods
1599

1600    public static void generateCode(AspectConfiguration ac) throws Exception {
1601        Project project = ac.getApplication().getProject();
1602        project.checkGenerationPath();
1603        CodeGeneration.createACFile(
1604            project,ac,
1605            new File(project.getGenerationPath().getPath(),ac.getApplication().getGenerationName()));
1606    }
1607
1608    public static void generateAndReload(AspectConfiguration ac) throws Throwable {
1609        generateCode(ac);
1610        ac.reload();
1611    }
1612}
1613
Popular Tags