1 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 ; 37 import java.io.File ; 38 import java.io.FileFilter ; 39 import java.io.FileReader ; 40 import java.io.IOException ; 41 import java.util.ArrayList ; 42 import java.util.Collection ; 43 import java.util.Collections ; 44 import java.util.HashMap ; 45 import java.util.HashSet ; 46 import java.util.Iterator ; 47 import java.util.List ; 48 import java.util.Map ; 49 import java.util.Set ; 50 import java.util.StringTokenizer ; 51 52 58 public class AjdocCompiler extends AspectJCompiler implements RootDocMaker { 59 60 61 protected final String programName; 62 63 64 protected final ErrPrinter err; 65 66 74 public AjdocCompiler(ErrorHandler errorHandler, String 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 89 public AjdocCompiler(String programName) { 90 this(null, programName); 91 } 92 93 98 public ErrPrinter err() { 99 return err; 100 } 101 102 103 private Set pkgnames = new HashSet (); 104 105 106 private Set classnames = new HashSet (); 107 108 109 private Set files = new HashSet (); 110 111 112 protected final List srcfiles = new ArrayList (); 113 114 115 protected List srcSrcfilenames = new ArrayList (); 116 117 118 protected List pkgSrcfilenames = new ArrayList (); 119 120 121 protected List clsSrcfilenames = new ArrayList (); 122 123 124 protected final List sourcepaths = new ArrayList (); 125 { 126 sourcepaths.add(new File (".")); 127 } 128 129 protected AccessChecker filter; 130 131 134 public RootDoc makeRootDoc(String sourcepath, 135 String classpath, 136 String bootclasspath, 137 String extdirs, 138 long flags, 139 String encoding, 140 String locale, 141 String source, 142 List filenamesAndPackages, 143 List options, 144 DocErrorReporter err, 145 String 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 i = options.iterator(); i.hasNext();) { 178 String [] opts = (String [])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 addPasses(); 196 internalCompile(srcfiles); 197 198 World world = getWorld(); 200 201 for (Iterator 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 err().notice("creating_root"); 217 RootDoc result = init(this, (String [][])options.toArray 218 (new String [options.size()][])); 219 220 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 248 public static RootDocImpl init(AspectJCompiler ajc, String [][] options) { 249 250 if (ajc == null) return null; 252 World world = ajc.getWorld(); 253 254 Collection classnames = null; 255 Collection 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 277 protected void setFilter(AccessChecker filter, String arg) { 278 this.filter = filter; 279 } 280 281 282 public final AccessChecker getFilter() { 283 return filter; 284 } 285 286 protected final void expandAtFile(String filename, 287 List args) throws IOException { 288 BufferedReader in = new BufferedReader (new FileReader (filename)); 289 String dirfile = new File (filename).getParent(); 290 File basedir = new File (null == dirfile ? "." : dirfile ) ; 291 String 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 newfile = new File (line); 300 newfile = newfile.isAbsolute() ? 301 newfile : new File (basedir, line); 302 expandAtFile(newfile.getPath(), args); 303 } else { 304 File newfile = new File (line); 305 newfile = newfile.isAbsolute() ? 306 newfile : new File (basedir, line); 307 if (newfile.exists()) { 308 boolean result = maybeAdd(newfile, args); 309 if (!result) { 310 cantResolve(newfile); 312 } 313 } else { 314 boolean addedFile = false; 315 FileFilter filter = null; 316 String name = newfile.getName().trim(); 317 if (name.equals("*.java")) { 318 filter = new FileFilter () { 319 public boolean accept(File f) { 320 return f != null && 321 f.getName().endsWith(".java"); 322 } 323 }; 324 } else if (name.equals("*.aj")) { 325 filter = new FileFilter () { 326 public boolean accept(File f) { 327 return f != null && 328 f.getName().endsWith(".java"); 329 } 330 }; 331 } else if (name.equals("*")) { 332 filter = new FileFilter () { 333 public boolean accept(File f) { 334 return f != null && 335 (f.getName().endsWith(".java") 336 || f.getName().endsWith(".aj")); 337 } 338 }; 339 } 340 if (null != filter) { 341 File parentDir = newfile.getParentFile(); 342 File [] 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 f) { 367 err().error("cant_resolve_file", f.getAbsolutePath()); 368 } 369 370 private void resolveSourcePath(String sourcepath) { 371 if (sourcepath != null) { 372 sourcepaths.remove(0); 373 for (StringTokenizer t = new StringTokenizer (sourcepath, 374 File.pathSeparator); 375 t.hasMoreTokens();) { 376 File path = new File (t.nextToken().trim()); 377 if (path.exists() && path.isDirectory()) { 378 sourcepaths.add(path); 379 } 380 } 381 } 384 } 385 386 private void resolveFilesAndPackages(List filenamesAndPackages) { 387 Collection pkgnamesFromCmd = new HashSet (); 388 for (Iterator i = filenamesAndPackages.iterator(); i.hasNext();) { 389 String str = (String )i.next(); 390 File file = new File (str); 391 if ( maybeAdd(file, srcSrcfilenames)) { 392 addFile(file); 393 continue; 394 } else { 395 for (Iterator j = sourcepaths.iterator(); j.hasNext();) { 396 File sourcepath = (File )j.next(); 397 file = new File (sourcepath, str); 398 if (maybeAdd(file, srcSrcfilenames)) { 399 addFile(file); 400 continue; 401 } 402 } 403 } 404 pkgnamesFromCmd.add(str); 405 } 406 for (Iterator i = pkgnamesFromCmd.iterator(); i.hasNext();) { 407 resolvePackageOrClass((String )i.next()); 408 } 409 } 410 411 private void resolvePackageOrClass(String pkgOrClassName) { 412 boolean recurse; 413 String pkgOrClass = 414 (recurse = (pkgOrClassName.endsWith(".*"))) ? 415 pkgOrClassName.substring(0, pkgOrClassName.length()-2) : 416 pkgOrClassName; 417 for (Iterator i = sourcepaths.iterator(); i.hasNext();) { 418 File sourcepath = (File )i.next(); 419 File possiblePkg = new File (sourcepath, 420 pkgOrClass.replace 421 ('.', File.separatorChar)); 422 if (possiblePkg.exists() && possiblePkg.isDirectory()) { 423 if (recurse) { 424 File [] dirs = possiblePkg.listFiles 425 (new FileFilter () { 426 public boolean accept(File f) { 427 return f != null && f.isDirectory(); 428 } 429 }); 430 for (int j = 0; j < dirs.length; j++) { 431 String pkgname = pkgOrClass + '.' + dirs[j].getName(); 432 resolvePackageOrClass(pkgname + ".*"); 433 } 434 } 435 File [] javafiles = possiblePkg.listFiles 436 (new FileFilter () { 437 public boolean accept(File 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 pkgname = ""; 454 String 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 file = new File (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 findFile(String filename, boolean isDir) { 472 for (Iterator i = sourcepaths.iterator(); i.hasNext();) { 473 File sourcepath = (File )i.next(); 474 File file = new File (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 pkgname, 483 Collection pkgnames) { 484 if (isValidPkg(pkgname)) { 485 pkgnames.add(pkgname); 486 return true; 487 } 488 return false; 489 } 490 491 protected final Map filesToClassnames = new HashMap (); 492 protected final void addClass(String classname, File 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 classname) { 501 return maybeAddClass(classname, classnames); 502 } 503 504 protected static boolean maybeAddClass(String classname, 505 Collection 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 classname) { 514 return isValidPkg(classname); 515 } 516 517 protected final Map filesToPkgnames = new HashMap (); 518 protected final void addPkg(String pkgname, File 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 pkgname) { 527 return maybeAddPkg(pkgname, pkgnames); 528 } 529 530 protected final Map filesToFilenames = new HashMap (); 531 protected final void addFile(File file) { 532 files.add(file); 533 filesToFilenames.put(file.getAbsoluteFile(), file.getAbsolutePath()); 534 } 535 536 protected static boolean maybeAdd(File file, Collection 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 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 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 srcfile = cu.getSourceFile().getAbsoluteFile(); 574 String pkgname, classname, filename; 575 if ((pkgname = (String )filesToPkgnames.get(srcfile))!= null) { 576 AjdocCompiler.this.err().notice 577 ("Loading_source_files_for_package", pkgname); 578 } else if ((classname = (String )filesToClassnames.get(srcfile)) != null) { 579 AjdocCompiler.this.err().notice 580 ("Loading_source_file_for_class", classname); 581 } else if ((filename = (String )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 (); 601 addPreSymbolPasses(); 602 } 603 } 604 | Popular Tags |