KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > tools > ajdoc > AjdocCompiler


1 /* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the debugger and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  */

22 package org.aspectj.tools.ajdoc;
23
24 import org.aspectj.compiler.base.AbstractCompilerPass;
25 import org.aspectj.compiler.base.ErrorHandler;
26 import org.aspectj.compiler.base.ast.CompilationUnit;
27 import org.aspectj.compiler.base.ast.Dec;
28 import org.aspectj.compiler.base.ast.Decs;
29 import org.aspectj.compiler.base.ast.TypeDec;
30 import org.aspectj.compiler.base.ast.World;
31 import org.aspectj.compiler.crosscuts.AspectJCompiler;
32
33 import com.sun.javadoc.DocErrorReporter;
34 import com.sun.javadoc.RootDoc;
35
36 import java.io.BufferedReader JavaDoc;
37 import java.io.File JavaDoc;
38 import java.io.FileFilter JavaDoc;
39 import java.io.FileReader JavaDoc;
40 import java.io.IOException JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.Collection JavaDoc;
43 import java.util.Collections JavaDoc;
44 import java.util.HashMap JavaDoc;
45 import java.util.HashSet JavaDoc;
46 import java.util.Iterator JavaDoc;
47 import java.util.List JavaDoc;
48 import java.util.Map JavaDoc;
49 import java.util.Set JavaDoc;
50 import java.util.StringTokenizer JavaDoc;
51
52 /**
53  * Extension of the AspectJCompiler to provide
54  * functionality for creating documentation.
55  *
56  * @author Jeff Palm
57  */

58 public class AjdocCompiler extends AspectJCompiler implements RootDocMaker {
59
60     /** The name of the program. */
61     protected final String JavaDoc programName;
62
63     /** The error printer we use. */
64     protected final ErrPrinter err;
65
66     /**
67      * Construct a new ajdoc compile with the
68      * error handler <code>errorHandler</code> and
69      * name <code>programName</code>
70      *
71      * @param errorHandler the error handler.
72      * @param programName the name of the program.
73      */

74     public AjdocCompiler(ErrorHandler errorHandler, String JavaDoc programName) {
75         super(errorHandler);
76         getOptions().preprocess = true;
77         getOptions().nocomments = true;
78         (errorHandler = err =
79          new ErrPrinter(this.programName = programName)).
80             setCompiler(this);
81     }
82
83     /**
84      * Construct a new ajdoc compile with the
85      * name <code>programName</code>.
86      *
87      * @param programName the name of the program.
88      */

89     public AjdocCompiler(String JavaDoc programName) {
90         this(null, programName);
91     }
92
93     /**
94      * Returns the ErrPrinter currently used.
95      *
96      * @return the ErrPrinter currently used.
97      */

98     public ErrPrinter err() {
99         return err;
100     }
101
102     /** The packages found on the command line. */
103     private Set JavaDoc pkgnames = new HashSet JavaDoc();
104
105     /** The classes found on the command line and from files. */
106     private Set JavaDoc classnames = new HashSet JavaDoc();
107
108     /** The source files on the command line. */
109     private Set JavaDoc files = new HashSet JavaDoc();
110
111     /** The list of source files to compile. */
112     protected final List JavaDoc srcfiles = new ArrayList JavaDoc();
113
114     /** The list of filenames that came from user-specified source files. */
115     protected List JavaDoc srcSrcfilenames = new ArrayList JavaDoc();
116
117     /** The list of filenames that came from user-specified packages. */
118     protected List JavaDoc pkgSrcfilenames = new ArrayList JavaDoc();
119
120     /** The list of filenames that came from user-specified classes. */
121     protected List JavaDoc clsSrcfilenames = new ArrayList JavaDoc();
122
123     /** The source path with which to search. */
124     protected final List JavaDoc sourcepaths = new ArrayList JavaDoc();
125     {
126         sourcepaths.add(new File JavaDoc("."));
127     }
128     /** The list of filenames that came from user-specified classes. */
129     protected AccessChecker filter;
130
131     /**
132      * Create the RootDoc.
133      */

134     public RootDoc makeRootDoc(String JavaDoc sourcepath,
135                                String JavaDoc classpath,
136                                String JavaDoc bootclasspath,
137                                String JavaDoc extdirs,
138                                long flags,
139                                String JavaDoc encoding,
140                                String JavaDoc locale,
141                                String JavaDoc source,
142                                List JavaDoc filenamesAndPackages,
143                                List JavaDoc options,
144                                DocErrorReporter err,
145                                String JavaDoc programName,
146                                AccessChecker filter)
147         throws CannotMakeRootDocException {
148         if ((null != filter) && (this.filter != filter)) {
149             this.filter = filter;
150         }
151         if (null == this.filter) {
152             this.filter = AccessChecker.PROTECTED;
153         }
154         if (classpath != null) {
155             getOptions().classpath = classpath;
156         }
157         if (bootclasspath != null) {
158             getOptions().bootclasspath = bootclasspath;
159         }
160         if (extdirs != null) {
161             getOptions().extdirs = extdirs;
162         }
163
164         resolveSourcePath(sourcepath);
165         resolveFilesAndPackages(filenamesAndPackages);
166
167         Collections.sort(pkgSrcfilenames);
168         Collections.sort(clsSrcfilenames);
169         Collections.sort(srcSrcfilenames);
170
171         srcfiles.addAll(pkgSrcfilenames);
172         srcfiles.addAll(clsSrcfilenames);
173         srcfiles.addAll(srcSrcfilenames);
174
175         err().notice("starting_internal_compile");
176
177         for (Iterator JavaDoc i = options.iterator(); i.hasNext();) {
178             String JavaDoc[] opts = (String JavaDoc[])i.next();
179             if (opts.length == 1) {
180                 if (opts[0].equals("-verbose")) {
181                     getOptions().verbose = true;
182                 }
183             } else if (opts.length == 2) {
184                 if (opts[0].equals("-classpath")) {
185                     getOptions().classpath = opts[1];
186                 } else if (opts[1].equals("-bootclasspath")) {
187                     getOptions().bootclasspath = opts[1];
188                 } else if (opts[1].equals("-extdirs")) {
189                     getOptions().extdirs = opts[1];
190                 }
191             }
192         }
193
194         // Compile the srcfiles - have to add passes first
195
addPasses();
196         internalCompile(srcfiles);
197
198         // This is the world with which we create the root
199
World world = getWorld();
200
201         // Add all the classes found in the source files
202
// to the list of specified classnames
203
for (Iterator JavaDoc i = world.getCompilationUnits().iterator();
204              i.hasNext();) {
205             Decs decs = ((CompilationUnit)i.next()).getDecs();
206             for (int j = 0, N = decs.size(); j < N; j++) {
207                 Dec dec = decs.get(j);
208                 if (dec instanceof TypeDec) {
209                     classnames.add(((TypeDec)dec).getFullName());
210                 }
211             }
212         }
213
214         // Initialize and return the root created
215
// from the our world
216
err().notice("creating_root");
217         RootDoc result = init(this, (String JavaDoc[][])options.toArray
218                     (new String JavaDoc[options.size()][]));
219                     
220         // do another pass at RootDoc after constructed
221
com.sun.javadoc.ClassDoc[] cds = result.classes();
222         for (int i = 0; i < cds.length; i++) {
223             if (cds[i] instanceof ClassDocImpl) {
224                 ClassDocImpl cd = (ClassDocImpl) cds[i];
225                 cd.postProcess();
226             }
227         }
228         return result;
229     }
230     
231
232     private static AjdocCompiler instance;
233     { instance = this; }
234
235     public static AjdocCompiler instance() {
236         return instance;
237     }
238
239     /**
240      * The entry point to initialize a world created
241      * from an AspectJCompiler.
242      *
243      * @param ajc the compiler.
244      * @param options the ajdoc options.
245      * @return a RootDocImpl representing the
246      * documentation tree.
247      */

248     public static RootDocImpl init(AspectJCompiler ajc, String JavaDoc[][] options) {
249
250         if (ajc == null) return null; //TODO: make empty
251

252         World world = ajc.getWorld();
253
254         Collection JavaDoc classnames = null;
255         Collection JavaDoc pkgnames = null;
256         if (ajc instanceof AjdocCompiler) {
257             AjdocCompiler ajdoc = (AjdocCompiler)ajc;
258             pkgnames = ajdoc.pkgnames;
259             classnames = ajdoc.classnames;
260         }
261
262         PackageDocImpl.init(ajc);
263
264         AccessChecker filter = AccessChecker.PUBLIC;
265         if (ajc instanceof AjdocCompiler) {
266             filter = ((AjdocCompiler) ajc).getFilter();
267         }
268         RootDocImpl root = new RootDocImpl(world,
269                                            options,
270                                            pkgnames,
271                                            classnames,
272                                            filter);
273         return root;
274     }
275
276     /** set filter associated with this compiler */
277     protected void setFilter(AccessChecker filter, String JavaDoc arg) {
278         this.filter = filter;
279     }
280
281     /** get filter associated with this compiler */
282     public final AccessChecker getFilter() {
283         return filter;
284     }
285
286     protected final void expandAtFile(String JavaDoc filename,
287                                       List JavaDoc args) throws IOException JavaDoc {
288         BufferedReader JavaDoc in = new BufferedReader JavaDoc(new FileReader JavaDoc(filename));
289         String JavaDoc dirfile = new File JavaDoc(filename).getParent();
290         File JavaDoc basedir = new File JavaDoc(null == dirfile ? "." : dirfile ) ;
291         String JavaDoc line;
292         while ((line = in.readLine()) != null) {
293             if (line == null || line.length() < 1) continue;
294             line = line.trim();
295             if (line.startsWith("//")) continue;
296             if (line.startsWith("#")) continue;
297             if (line.startsWith("@")) {
298                 line = line.substring(1);
299                 File JavaDoc newfile = new File JavaDoc(line);
300                 newfile = newfile.isAbsolute() ?
301                     newfile : new File JavaDoc(basedir, line);
302                 expandAtFile(newfile.getPath(), args);
303             } else {
304                 File JavaDoc newfile = new File JavaDoc(line);
305                 newfile = newfile.isAbsolute() ?
306                     newfile : new File JavaDoc(basedir, line);
307                 if (newfile.exists()) {
308                     boolean result = maybeAdd(newfile, args);
309                     if (!result) {
310                         // we only support valid filenames, not options
311
cantResolve(newfile);
312                     }
313                 } else {
314                     boolean addedFile = false;
315                     FileFilter JavaDoc filter = null;
316                     String JavaDoc name = newfile.getName().trim();
317                     if (name.equals("*.java")) {
318                         filter = new FileFilter JavaDoc() {
319                                     public boolean accept(File JavaDoc f) {
320                                         return f != null &&
321                                             f.getName().endsWith(".java");
322                                     }
323                                 };
324                     } else if (name.equals("*.aj")) {
325                         filter = new FileFilter JavaDoc() {
326                                     public boolean accept(File JavaDoc f) {
327                                         return f != null &&
328                                             f.getName().endsWith(".java");
329                                     }
330                                 };
331                     } else if (name.equals("*")) {
332                         filter = new FileFilter JavaDoc() {
333                                     public boolean accept(File JavaDoc f) {
334                                         return f != null &&
335                                             (f.getName().endsWith(".java")
336                                             || f.getName().endsWith(".aj"));
337                                     }
338                                 };
339                     }
340                     if (null != filter) {
341                         File JavaDoc parentDir = newfile.getParentFile();
342                         File JavaDoc[] javafiles = parentDir.listFiles(filter);
343                         if (javafiles != null) {
344                             for (int i = 0; i < javafiles.length; i++) {
345                                 if (maybeAdd(javafiles[i], args)) {
346                                     if (!addedFile) addedFile = true;
347                                 } else {
348                                     cantResolve(javafiles[i]);
349                                 }
350                             }
351                         }
352                     }
353                     if (!addedFile) {
354                         if (isValidPkg(line)) {
355                             args.add(line);
356                         } else {
357                             cantResolve(newfile);
358                         }
359                     }
360                 }
361             }
362         }
363         in.close();
364     }
365
366     protected final void cantResolve(File JavaDoc f) {
367         err().error("cant_resolve_file", f.getAbsolutePath());
368     }
369
370     private void resolveSourcePath(String JavaDoc sourcepath) {
371         if (sourcepath != null) {
372             sourcepaths.remove(0);
373             for (StringTokenizer JavaDoc t = new StringTokenizer JavaDoc(sourcepath,
374                                                          File.pathSeparator);
375                  t.hasMoreTokens();) {
376                 File JavaDoc path = new File JavaDoc(t.nextToken().trim());
377                 if (path.exists() && path.isDirectory()) {
378                     sourcepaths.add(path);
379                 }
380             }
381             // TODO: don't want this, I think ????
382
//sourcepaths.add(new File("."));
383
}
384     }
385
386     private void resolveFilesAndPackages(List JavaDoc filenamesAndPackages) {
387         Collection JavaDoc pkgnamesFromCmd = new HashSet JavaDoc();
388         for (Iterator JavaDoc i = filenamesAndPackages.iterator(); i.hasNext();) {
389             String JavaDoc str = (String JavaDoc)i.next();
390             File JavaDoc file = new File JavaDoc(str);
391             if (/*file.isAbsolute() &&*/ maybeAdd(file, srcSrcfilenames)) {
392                 addFile(file);
393                 continue;
394             } else {
395                 for (Iterator JavaDoc j = sourcepaths.iterator(); j.hasNext();) {
396                     File JavaDoc sourcepath = (File JavaDoc)j.next();
397                     file = new File JavaDoc(sourcepath, str);
398                     if (maybeAdd(file, srcSrcfilenames)) {
399                         addFile(file);
400                         continue;
401                     }
402                 }
403             }
404             pkgnamesFromCmd.add(str);
405         }
406         for (Iterator JavaDoc i = pkgnamesFromCmd.iterator(); i.hasNext();) {
407             resolvePackageOrClass((String JavaDoc)i.next());
408         }
409     }
410
411     private void resolvePackageOrClass(String JavaDoc pkgOrClassName) {
412         boolean recurse;
413         String JavaDoc pkgOrClass =
414             (recurse = (pkgOrClassName.endsWith(".*"))) ?
415             pkgOrClassName.substring(0, pkgOrClassName.length()-2) :
416             pkgOrClassName;
417         for (Iterator JavaDoc i = sourcepaths.iterator(); i.hasNext();) {
418             File JavaDoc sourcepath = (File JavaDoc)i.next();
419             File JavaDoc possiblePkg = new File JavaDoc(sourcepath,
420                                         pkgOrClass.replace
421                                         ('.', File.separatorChar));
422             if (possiblePkg.exists() && possiblePkg.isDirectory()) {
423                 if (recurse) {
424                     File JavaDoc[] dirs = possiblePkg.listFiles
425                         (new FileFilter JavaDoc() {
426                                 public boolean accept(File JavaDoc f) {
427                                     return f != null && f.isDirectory();
428                                 }
429                             });
430                     for (int j = 0; j < dirs.length; j++) {
431                         String JavaDoc pkgname = pkgOrClass + '.' + dirs[j].getName();
432                         resolvePackageOrClass(pkgname + ".*");
433                     }
434                 }
435                 File JavaDoc[] javafiles = possiblePkg.listFiles
436                     (new FileFilter JavaDoc() {
437                             public boolean accept(File JavaDoc f) {
438                                 return f != null && !f.isDirectory();
439                             }
440                         });
441                 if (javafiles.length > 0) {
442                     pkgnames.add(pkgOrClass);
443                 }
444                 boolean addedPkg = false;
445                 for (int j = 0; j < javafiles.length; j++) {
446                     if (maybeAdd(javafiles[j], pkgSrcfilenames) && !addedPkg) {
447                         addPkg(pkgOrClass, javafiles[j]);
448                         addedPkg = true;
449                     }
450                 }
451                 break;
452             } else {
453                 String JavaDoc pkgname = "";
454                 String JavaDoc classname = pkgOrClass;
455                 int ilastdot = pkgOrClass.lastIndexOf('.');
456                 if (ilastdot != -1) {
457                     pkgname = pkgOrClass.substring(0, ilastdot).
458                         replace('.', File.separatorChar) + File.separatorChar;
459                     classname = pkgOrClass.substring(ilastdot+1);
460                 }
461                 File JavaDoc file = new File JavaDoc(sourcepath,
462                                      pkgname + classname + ".java");
463                 if (maybeAdd(file, clsSrcfilenames)) {
464                     addClass(pkgOrClass, file);
465                     break;
466                 }
467             }
468         }
469     }
470
471     protected final File JavaDoc findFile(String JavaDoc filename, boolean isDir) {
472         for (Iterator JavaDoc i = sourcepaths.iterator(); i.hasNext();) {
473             File JavaDoc sourcepath = (File JavaDoc)i.next();
474             File JavaDoc file = new File JavaDoc(sourcepath, filename);
475             if (file.exists() && !(isDir ^ file.isDirectory())) {
476                 return file;
477             }
478         }
479         return null;
480     }
481
482     protected static boolean maybeAddPkg(String JavaDoc pkgname,
483                                          Collection JavaDoc pkgnames) {
484         if (isValidPkg(pkgname)) {
485             pkgnames.add(pkgname);
486             return true;
487         }
488         return false;
489     }
490
491     protected final Map JavaDoc filesToClassnames = new HashMap JavaDoc();
492     protected final void addClass(String JavaDoc classname, File JavaDoc file) {
493         if (!(maybeAddClass(classname))) {
494             err().error("invalid_class_name", classname);
495         } else {
496             filesToClassnames.put(file.getAbsoluteFile(), classname);
497         }
498     }
499
500     protected final boolean maybeAddClass(String JavaDoc classname) {
501         return maybeAddClass(classname, classnames);
502     }
503
504     protected static boolean maybeAddClass(String JavaDoc classname,
505                                            Collection JavaDoc classnames) {
506         if (isValidClass(classname)) {
507             classnames.add(classname);
508             return true;
509         }
510         return false;
511     }
512
513     protected final static boolean isValidClass(String JavaDoc classname) {
514         return isValidPkg(classname);
515     }
516
517     protected final Map JavaDoc filesToPkgnames = new HashMap JavaDoc();
518     protected final void addPkg(String JavaDoc pkgname, File JavaDoc file) {
519         if (!maybeAddPkg(pkgname)) {
520             err().error("invalid_package_name", pkgname);
521         } else {
522             filesToPkgnames.put(file.getAbsoluteFile(), pkgname);
523        }
524     }
525
526     protected final boolean maybeAddPkg(String JavaDoc pkgname) {
527         return maybeAddPkg(pkgname, pkgnames);
528     }
529
530     protected final Map JavaDoc filesToFilenames = new HashMap JavaDoc();
531     protected final void addFile(File JavaDoc file) {
532         files.add(file);
533         filesToFilenames.put(file.getAbsoluteFile(), file.getAbsolutePath());
534     }
535
536     protected static boolean maybeAdd(File JavaDoc file, Collection JavaDoc files) {
537         if (isValidJavaFile(file)) {
538             files.add(file.getAbsolutePath());
539             return true;
540         }
541         return false;
542     }
543
544     protected final static boolean isValidJavaFile(File JavaDoc file) {
545         return file != null && file.exists() && !file.isDirectory()
546             && (file.getName().endsWith(".java")
547                 || file.getName().endsWith(".aj")) ;
548     }
549
550     protected final static boolean isValidPkg(String JavaDoc pkgname) {
551         if (pkgname == null) {
552             return false;
553         }
554         if (pkgname.length() < 1) {
555             return true;
556         }
557         if (!Character.isJavaIdentifierStart(pkgname.charAt(0))) {
558             return false;
559         }
560         for (int i = 1; i < pkgname.length(); i++) {
561             char c = pkgname.charAt(i);
562             if (c == '.' && i == pkgname.length()-1) {
563                 return false;
564             }
565             if (!(c == '.' || Character.isJavaIdentifierPart(c))) {
566                 return false;
567             }
568         }
569         return true;
570     }
571
572     protected void loading(CompilationUnit cu) {
573         File JavaDoc srcfile = cu.getSourceFile().getAbsoluteFile();
574         String JavaDoc pkgname, classname, filename;
575         if ((pkgname = (String JavaDoc)filesToPkgnames.get(srcfile))!= null) {
576             AjdocCompiler.this.err().notice
577                 ("Loading_source_files_for_package", pkgname);
578         } else if ((classname = (String JavaDoc)filesToClassnames.get(srcfile)) != null) {
579             AjdocCompiler.this.err().notice
580                 ("Loading_source_file_for_class", classname);
581         } else if ((filename = (String JavaDoc)filesToFilenames.get(srcfile)) != null) {
582             AjdocCompiler.this.err().notice
583                 ("Loading_source_file", filename);
584         }
585     }
586
587     protected AbstractCompilerPass createParserPass() {
588         return new PrintingParserPass(this);
589     }
590     
591     protected static class PrintingParserPass extends AspectJCompiler.ParserPass {
592         public PrintingParserPass(AjdocCompiler jc) { super(jc); }
593         public void transform(CompilationUnit cu) {
594             ((AjdocCompiler)getCompiler()).loading(cu);
595             super.transform(cu);
596         }
597     }
598
599     protected void addPasses() {
600         passes = new ArrayList JavaDoc();
601         addPreSymbolPasses();
602     }
603 }
604
Popular Tags