1 33 34 package edu.rice.cs.drjava.model; 35 36 import java.io.File ; 37 import java.io.IOException ; 38 import java.util.HashSet ; 39 import java.util.ArrayList ; 40 import java.util.LinkedList ; 41 import java.util.List ; 42 import java.util.Collection ; 43 44 import edu.rice.cs.plt.io.IOUtil; 45 import edu.rice.cs.util.FileOps; 46 import edu.rice.cs.util.ArgumentTokenizer; 47 import edu.rice.cs.util.DirectorySelector; 48 import edu.rice.cs.util.FileOpenSelector; 49 import edu.rice.cs.drjava.model.FileSaveSelector; 50 import edu.rice.cs.util.OperationCanceledException; 51 import edu.rice.cs.util.newjvm.ExecJVM; 52 import edu.rice.cs.drjava.DrJava; 53 import edu.rice.cs.drjava.config.Configuration; 54 import edu.rice.cs.drjava.config.OptionConstants; 55 import edu.rice.cs.drjava.config.FileOption; 56 import edu.rice.cs.drjava.platform.PlatformFactory; 57 import edu.rice.cs.drjava.platform.PlatformSupport; 58 import edu.rice.cs.drjava.model.compiler.CompilerErrorModel; 59 import edu.rice.cs.drjava.model.compiler.CompilerError; 60 import edu.rice.cs.drjava.model.definitions.InvalidPackageException; 61 62 65 public class DefaultJavadocModel implements JavadocModel { 66 67 68 private GlobalModel _model; 69 70 71 private final JavadocEventNotifier _notifier = new JavadocEventNotifier(); 72 73 74 private CompilerErrorModel _javadocErrorModel; 75 76 79 public DefaultJavadocModel(GlobalModel model) { 80 _model = model; 81 _javadocErrorModel = new CompilerErrorModel(); 82 } 83 84 86 89 public void addListener(JavadocListener listener) { _notifier.addListener(listener); } 90 91 95 public void removeListener(JavadocListener listener) { _notifier.removeListener(listener); } 96 97 98 public void removeAllListeners() { _notifier.removeAllListeners(); } 99 100 102 105 public CompilerErrorModel getJavadocErrorModel() { return _javadocErrorModel; } 106 107 108 public void resetJavadocErrors() { 109 _javadocErrorModel = new CompilerErrorModel(); 110 } 111 112 114 121 public void javadocAll(DirectorySelector select, final FileSaveSelector saver, final String classPath) 122 throws IOException { 123 124 126 if (_model.hasModifiedDocuments() || _model.hasUntitledDocuments()) { return; } 127 128 Configuration config = DrJava.getConfig(); 129 File destDir = config.getSetting(OptionConstants.JAVADOC_DESTINATION); 130 131 try { 133 if (destDir.equals(FileOption.NULL_FILE)) { 134 136 destDir = select.getDirectory(null); 137 } 138 else 139 destDir = select.getDirectory(destDir); 141 142 while (!destDir.exists() || !destDir.isDirectory() || !destDir.canWrite()) { 144 if (!destDir.getPath().equals("") && !destDir.exists()) { 145 boolean create = select.askUser 147 ("The directory you chose does not exist:\n'" + destDir + "'\nWould you like to create it?", 148 "Create Directory?"); 149 if (create) { 150 boolean dirMade = destDir.mkdirs(); 151 if (! dirMade) throw new IOException ("Could not create directory: " + destDir); 152 } 153 else return; 154 } 155 else if (!destDir.isDirectory() || destDir.getPath().equals("")) { 156 select.warnUser("The file you chose is not a directory:\n" + 158 "'" + destDir + "'\n" + 159 "Please choose another.", 160 "Not a Directory!"); 161 destDir = select.getDirectory(null); 162 } 163 else { 164 select.warnUser("The directory you chose is not writable:\n" + 166 "'" + destDir + "'\n" + 167 "Please choose another directory.", 168 "Cannot Write to Destination!"); 169 destDir = select.getDirectory(null); 170 } 171 } 172 } 173 catch (OperationCanceledException oce) { return; } 175 _notifier.javadocStarted(); final File destDirF = destDir; 178 new Thread ("DrJava Javadoc Thread") { 179 public void run() { _javadocAllWorker(destDirF, saver, classPath); } 180 }.start(); 181 } 182 183 188 private void _javadocAllWorker(File destDirFile, FileSaveSelector saver, String classPath) { 189 190 192 String destDir = destDirFile.getAbsolutePath(); 193 194 HashSet <String > docUnits = new HashSet <String >(); HashSet <File > sourceRootSet = new HashSet <File >(); HashSet <File > defaultRoots = new HashSet <File >(); HashSet <String > topLevelPacks = new HashSet <String >(); 200 boolean docAll = DrJava.getConfig().getSetting(OptionConstants.JAVADOC_FROM_ROOTS).booleanValue(); 202 203 for (OpenDefinitionsDocument doc: _model.getOpenDefinitionsDocuments()) { 205 File file = null; 206 207 try { 208 file = _getFileFromDocument(doc, saver); 210 211 if (file == null) throw new IllegalStateException ("No file for this document."); 213 214 File sourceRoot = doc.getSourceRoot(); 215 String pack = doc.getPackageName(); 216 217 if (pack.equals("")) { 218 if (! defaultRoots.contains(sourceRoot)) { 220 defaultRoots.add(sourceRoot); 224 Iterable <File > javaFiles = IOUtil.attemptListFilesAsIterable(sourceRoot, IOUtil.extensionFileFilter("java")); 225 for (File f: javaFiles) { docUnits.add(f.getAbsolutePath()); } 226 } 227 } 228 else { 229 String topLevelPack; 231 File searchRoot; 232 233 int index = pack.indexOf('.'); 234 if (docAll && index != -1) { 235 237 topLevelPack = pack.substring(0, index); 240 searchRoot = new File (sourceRoot, topLevelPack); 241 } 242 else { 243 topLevelPack = pack; 245 searchRoot = new File (sourceRoot, pack.replace('.', File.separatorChar)); 246 } 247 248 if (! topLevelPacks.contains(topLevelPack) || ! sourceRootSet.contains(sourceRoot)) { 250 topLevelPacks.add(topLevelPack); 252 sourceRootSet.add(sourceRoot); 253 docUnits.addAll(FileOps.packageExplore(topLevelPack, searchRoot)); 254 } 255 } 256 } 257 catch (IllegalStateException ise) { 258 } 260 catch (IOException ioe) { 261 _showCompilerError(ioe.getMessage(), file); 265 return; 266 } 267 catch (InvalidPackageException ipe) { 268 _showCompilerError(ipe.getMessage(), file); 272 return; 273 } 274 } 275 276 if (docUnits.size() == 0) return; 278 279 final StringBuilder sourcePath = new StringBuilder (); 281 final String separator = System.getProperty("path.separator"); 282 sourceRootSet.addAll(defaultRoots); 283 final File [] sourceRoots = sourceRootSet.toArray(new File [sourceRootSet.size()]); 284 for (int a = 0 ; a < sourceRoots.length; a++) { 285 if (a != 0) sourcePath.append(separator); 286 sourcePath.append(sourceRoots[a].getAbsolutePath()); 287 } 288 289 ArrayList <String > args = _buildCommandLineArgs(docUnits, destDir, sourcePath.toString(), classPath); 291 292 _runJavadoc(args, classPath, destDirFile, true); 294 } 295 296 297 298 300 308 public void javadocDocument(final OpenDefinitionsDocument doc, final FileSaveSelector saver, final String classPath) 309 throws IOException { 310 if (doc.isUntitled() || doc.isModifiedSinceSave()) _notifier.saveBeforeJavadoc(); 313 314 if (doc.isUntitled() || doc.isModifiedSinceSave()) return; 317 final File file = _getFileFromDocument(doc, saver); 319 320 final File destDir = IOUtil.createAndMarkTempDirectory("DrJava-javadoc", ""); 322 323 _notifier.javadocStarted(); new Thread ("DrJava Javadoc Thread") { 326 public void run() { _javadocDocumentWorker(destDir, file, classPath); } 327 }.start(); 328 } 329 330 335 private void _javadocDocumentWorker(File destDir, File docFile, String classPath) { 336 338 String destDirName = destDir.getAbsolutePath(); 340 ArrayList <String > args = _buildCommandLineArgs(docFile, destDirName, classPath); 341 342 _runJavadoc(args, classPath, destDir, false); 344 } 345 346 347 348 350 356 public File suggestJavadocDestination(OpenDefinitionsDocument doc) { 357 _attemptSaveAllDocuments(); 358 359 try { 360 File sourceRoot = doc.getSourceRoot(); 361 return new File (sourceRoot, SUGGESTED_DIR_NAME); 362 } 363 catch (InvalidPackageException ipe) { return null; } 364 } 365 366 373 private void _attemptSaveAllDocuments() { 374 if (_model.hasModifiedDocuments() || _model.hasUntitledDocuments()) _notifier.saveBeforeJavadoc(); 376 } 377 378 398 404 private void _showCompilerError(String msg, File f) { 405 CompilerError[] errors = new CompilerError[1]; 406 errors[0] = new CompilerError(f, -1, -1, msg, false); 407 _javadocErrorModel = new CompilerErrorModel(errors, _model); 408 _notifier.javadocEnded(false, null, false); 409 } 410 411 421 private void _runJavadoc(ArrayList <String > args, String classPath, File destDirFile, boolean allDocs) { 422 boolean result; 425 try { 426 429 result = _javadoc(args.toArray(new String [args.size()]), classPath); 430 431 if (result && !allDocs) IOUtil.deleteOnExitRecursively(destDirFile); 434 435 _notifier.javadocEnded(result, destDirFile, allDocs); 437 } 438 catch (Throwable e) { 439 _showCompilerError(e.getMessage(), null); 441 } 442 } 443 444 452 private boolean _javadoc(String [] args, String classPath) throws IOException { 453 final String JAVADOC_CLASS = "com.sun.tools.javadoc.Main"; 454 Process javadocProcess; 455 456 458 double version = Double.valueOf(System.getProperty("java.specification.version")); 459 String [] jvmArgs = new String [0]; 460 461 javadocProcess = ExecJVM.runJVM(JAVADOC_CLASS, args, new String []{classPath}, jvmArgs, FileOption.NULL_FILE); 463 464 466 469 471 LinkedList <String > outLines = new LinkedList <String >(); 473 LinkedList <String > errLines = new LinkedList <String >(); 474 boolean done = false; 475 while (!done) { 476 try { 477 Thread.sleep(500); 478 javadocProcess.exitValue(); 479 done = true; 480 } 481 catch (InterruptedException e) { 482 } 484 catch (IllegalThreadStateException e) { 485 ExecJVM.ventBuffers(javadocProcess, outLines, errLines); 486 } 487 } 488 ExecJVM.ventBuffers(javadocProcess, outLines, errLines); 489 491 494 ArrayList <CompilerError> errors = _extractErrors(outLines); 495 errors.addAll(_extractErrors(errLines)); 496 497 _javadocErrorModel = new CompilerErrorModel 498 (errors.toArray(new CompilerError[errors.size()]), _model); 499 501 return _javadocErrorModel.hasOnlyWarnings(); 503 } 504 505 514 private ArrayList <CompilerError> _extractErrors(LinkedList lines) { 515 ArrayList <CompilerError> errors = new ArrayList <CompilerError>(100); 517 518 final String ERROR_INDICATOR = "Error: "; 519 final String EXCEPTION_INDICATOR = "Exception: "; 520 final String BAD_FLAG_INDICATOR = "invalid flag:"; 521 while (lines.size() > 0) { 522 524 String output = (String ) lines.removeFirst(); 525 526 int errStart; 528 errStart = output.indexOf(ERROR_INDICATOR); 529 530 if (errStart == -1) { 532 errStart = output.indexOf(EXCEPTION_INDICATOR); 533 } 534 535 if (errStart == -1) { 537 errStart = output.indexOf(BAD_FLAG_INDICATOR); 538 } 539 540 if (errStart != -1) { 541 final StringBuilder buf = new StringBuilder (60 * lines.size()); 543 buf.append(output); 544 while (lines.size() > 0) { 545 output = (String ) lines.removeFirst(); 546 buf.append('\n'); 547 buf.append(output); 548 } 549 errors.add(new CompilerError(buf.toString(), false)); 550 } 551 else { 552 CompilerError error = _parseJavadocErrorLine(output); 554 if (error != null) { 555 errors.add(error); 556 } 558 } 559 } 560 561 return errors; 562 } 563 564 574 private CompilerError _parseJavadocErrorLine(String line) { 575 if (line == null) { 577 return null; 578 } 579 580 final String JAVA_INDICATOR = ".java:"; 581 final String GJ_INDICATOR = ".gj:"; 582 583 CompilerError error = null; 584 585 int errStart = line.indexOf(JAVA_INDICATOR); 588 589 if (errStart == -1) { 591 errStart = line.indexOf(GJ_INDICATOR); 592 } 593 594 if (errStart != -1) { 595 String fileName = line.substring(0, errStart+5); 597 598 int lineno = -1; 600 final StringBuilder linenoString = new StringBuilder (); 601 int pos = errStart+6; 602 while ((line.charAt(pos) >= '0') && (line.charAt(pos) <= '9')) { 603 linenoString.append(line.charAt(pos)); 604 pos++; 605 } 606 if (line.charAt(pos) == ':') { 610 try { 611 lineno = Integer.valueOf(linenoString.toString()).intValue() -1; 613 } catch (NumberFormatException e) { 614 } 615 } else { 616 pos = errStart; 617 } 618 619 String errMessage = line.substring(pos+2); 621 622 boolean isWarning = false; 624 if (errMessage.substring(0, 7).equalsIgnoreCase("warning")) { 625 isWarning = true; 626 } 627 628 if (lineno >= 0) { 629 error = new CompilerError(new File (fileName), lineno, 0, errMessage, false); 630 631 } else { 632 error = new CompilerError(new File (fileName), errMessage, false); 633 } 634 } 635 return error; 636 } 637 638 639 640 651 private File _getFileFromDocument(OpenDefinitionsDocument doc, FileSaveSelector saver) throws IOException { 652 try { 653 return doc.getFile(); 655 } 656 catch (FileMovedException fme) { 657 if (saver.shouldSaveAfterFileMoved(doc, fme.getFile())) { 660 try { 661 doc.saveFileAs(saver); 662 return doc.getFile(); 663 } 664 catch (FileMovedException fme2) { 665 fme2.printStackTrace(); 668 throw new IOException ("Could not find file: " + fme2); 669 } 670 } 671 else { 672 throw new IllegalStateException ("No file exists for this document."); 673 } 674 } 675 } 676 677 689 protected ArrayList <String > _buildCommandLineArgs(Collection <String > docUnits, 690 String destDir, 691 String sourcePath, 692 String classPath) 693 { 694 ArrayList <String > args = new ArrayList <String >(); 695 _addBasicArguments(args, destDir, sourcePath, classPath); 696 _addOnlineLinkArguments(args); 697 args.addAll(docUnits); 698 return args; 699 } 700 701 712 protected ArrayList <String > _buildCommandLineArgs(File file, String destDir, 713 String classPath) 714 { 715 ArrayList <String > args = new ArrayList <String >(); 716 _addBasicArguments(args, destDir, "", classPath); 717 _addSingleDocArguments(args); 718 args.add(file.getAbsolutePath()); 719 return args; 720 } 721 722 731 private void _addBasicArguments(ArrayList <String > args, 732 String destDir, 733 String sourcePath, 734 String classPath) 735 { 736 Configuration config = DrJava.getConfig(); 738 final String accLevel = config.getSetting(OptionConstants.JAVADOC_ACCESS_LEVEL); 739 final StringBuilder accArg = new StringBuilder (10); 740 accArg.append('-'); 741 accArg.append(accLevel); 742 743 args.add(accArg.toString()); 745 if (!sourcePath.equals("")) { 746 args.add("-sourcepath"); 747 args.add(sourcePath); 748 } 749 args.add("-d"); 750 args.add(destDir); 751 752 args.add("-classpath"); 754 args.add(classPath); 755 756 String custom = config.getSetting(OptionConstants.JAVADOC_CUSTOM_PARAMS); 758 args.addAll(ArgumentTokenizer.tokenize(custom)); 759 } 760 761 766 private void _addOnlineLinkArguments(ArrayList <String > args) { 767 Configuration config = DrJava.getConfig(); 768 String linkVersion = config.getSetting(OptionConstants.JAVADOC_LINK_VERSION); 769 if (linkVersion.equals(OptionConstants.JAVADOC_1_3_TEXT)) { 770 args.add("-link"); 771 args.add(config.getSetting(OptionConstants.JAVADOC_1_3_LINK)); 772 } 773 else if (linkVersion.equals(OptionConstants.JAVADOC_1_4_TEXT)) { 774 args.add("-link"); 775 args.add(config.getSetting(OptionConstants.JAVADOC_1_4_LINK)); 776 } 777 else if (linkVersion.equals(OptionConstants.JAVADOC_1_5_TEXT)) { 778 args.add("-link"); 779 args.add(config.getSetting(OptionConstants.JAVADOC_1_5_LINK)); 780 } 781 } 782 783 788 private void _addSingleDocArguments(ArrayList <String > args) { 789 args.add("-noindex"); 790 args.add("-notree"); 791 args.add("-nohelp"); 792 args.add("-nonavbar"); 793 } 794 } 795 | Popular Tags |