1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.doclets.internal.toolkit; 27 28 import java.io.*; 29 import java.util.*; 30 31 import com.sun.javadoc.*; 32 import com.sun.tools.javac.sym.Profiles; 33 import com.sun.tools.javac.jvm.Profile; 34 import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory; 35 import com.sun.tools.doclets.internal.toolkit.taglets.*; 36 import com.sun.tools.doclets.internal.toolkit.util.*; 37 import javax.tools.JavaFileManager; 38 39 /** 40 * Configure the output based on the options. Doclets should sub-class 41 * Configuration, to configure and add their own options. This class contains 42 * all user options which are supported by the 1.1 doclet and the standard 43 * doclet. 44 * 45 * <p><b>This is NOT part of any supported API. 46 * If you write code that depends on this, you do so at your own risk. 47 * This code and its internal interfaces are subject to change or 48 * deletion without notice.</b> 49 * 50 * @author Robert Field. 51 * @author Atul Dambalkar. 52 * @author Jamie Ho 53 */ 54 public abstract class Configuration { 55 56 /** 57 * The factory for builders. 58 */ 59 protected BuilderFactory builderFactory; 60 61 /** 62 * The taglet manager. 63 */ 64 public TagletManager tagletManager; 65 66 /** 67 * The path to the builder XML input file. 68 */ 69 public String builderXMLPath; 70 71 /** 72 * The default path to the builder XML. 73 */ 74 private static final String DEFAULT_BUILDER_XML = "resources/doclet.xml"; 75 76 /** 77 * The path to Taglets 78 */ 79 public String tagletpath = ""; 80 81 /** 82 * This is true if option "-serialwarn" is used. Defualt value is false to 83 * suppress excessive warnings about serial tag. 84 */ 85 public boolean serialwarn = false; 86 87 /** 88 * The specified amount of space between tab stops. 89 */ 90 public int sourcetab; 91 92 public String tabSpaces; 93 94 /** 95 * True if we should generate browsable sources. 96 */ 97 public boolean linksource = false; 98 99 /** 100 * True if command line option "-nosince" is used. Default value is 101 * false. 102 */ 103 public boolean nosince = false; 104 105 /** 106 * True if we should recursively copy the doc-file subdirectories 107 */ 108 public boolean copydocfilesubdirs = false; 109 110 /** 111 * The META charset tag used for cross-platform viewing. 112 */ 113 public String charset = ""; 114 115 /** 116 * True if user wants to add member names as meta keywords. 117 * Set to false because meta keywords are ignored in general 118 * by most Internet search engines. 119 */ 120 public boolean keywords = false; 121 122 /** 123 * The meta tag keywords instance. 124 */ 125 public final MetaKeywords metakeywords = new MetaKeywords(this); 126 127 /** 128 * The list of doc-file subdirectories to exclude 129 */ 130 protected Set<String> excludedDocFileDirs; 131 132 /** 133 * The list of qualifiers to exclude 134 */ 135 protected Set<String> excludedQualifiers; 136 137 /** 138 * The Root of the generated Program Structure from the Doclet API. 139 */ 140 public RootDoc root; 141 142 /** 143 * Destination directory name, in which doclet will generate the entire 144 * documentation. Default is current directory. 145 */ 146 public String destDirName = ""; 147 148 /** 149 * Destination directory name, in which doclet will copy the doc-files to. 150 */ 151 public String docFileDestDirName = ""; 152 153 /** 154 * Encoding for this document. Default is default encoding for this 155 * platform. 156 */ 157 public String docencoding = null; 158 159 /** 160 * True if user wants to suppress descriptions and tags. 161 */ 162 public boolean nocomment = false; 163 164 /** 165 * Encoding for this document. Default is default encoding for this 166 * platform. 167 */ 168 public String encoding = null; 169 170 /** 171 * Generate author specific information for all the classes if @author 172 * tag is used in the doc comment and if -author option is used. 173 * <code>showauthor</code> is set to true if -author option is used. 174 * Default is don't show author information. 175 */ 176 public boolean showauthor = false; 177 178 /** 179 * Generate version specific information for the all the classes 180 * if @version tag is used in the doc comment and if -version option is 181 * used. <code>showversion</code> is set to true if -version option is 182 * used.Default is don't show version information. 183 */ 184 public boolean showversion = false; 185 186 /** 187 * Sourcepath from where to read the source files. Default is classpath. 188 * 189 */ 190 public String sourcepath = ""; 191 192 /** 193 * Argument for command line option "-Xprofilespath". 194 */ 195 public String profilespath = ""; 196 197 /** 198 * Generate profiles documentation if profilespath is set and valid profiles 199 * are present. 200 */ 201 public boolean showProfiles = false; 202 203 /** 204 * Don't generate deprecated API information at all, if -nodeprecated 205 * option is used. <code>nodepracted</code> is set to true if 206 * -nodeprecated option is used. Default is generate deprected API 207 * information. 208 */ 209 public boolean nodeprecated = false; 210 211 /** 212 * The catalog of classes specified on the command-line 213 */ 214 public ClassDocCatalog classDocCatalog; 215 216 /** 217 * Message Retriever for the doclet, to retrieve message from the resource 218 * file for this Configuration, which is common for 1.1 and standard 219 * doclets. 220 * 221 * TODO: Make this private!!! 222 */ 223 public MessageRetriever message = null; 224 225 /** 226 * True if user wants to suppress time stamp in output. 227 * Default is false. 228 */ 229 public boolean notimestamp= false; 230 231 /** 232 * The package grouping instance. 233 */ 234 public final Group group = new Group(this); 235 236 /** 237 * The tracker of external package links. 238 */ 239 public final Extern extern = new Extern(this); 240 241 /** 242 * Return the build date for the doclet. 243 */ 244 public abstract String getDocletSpecificBuildDate(); 245 246 /** 247 * This method should be defined in all those doclets(configurations), 248 * which want to derive themselves from this Configuration. This method 249 * can be used to set its own command line options. 250 * 251 * @param options The array of option names and values. 252 * @throws DocletAbortException 253 */ 254 public abstract void setSpecificDocletOptions(String[][] options); 255 256 /** 257 * Return the doclet specific {@link MessageRetriever} 258 * @return the doclet specific MessageRetriever. 259 */ 260 public abstract MessageRetriever getDocletSpecificMsg(); 261 262 /** 263 * A profiles object used to access profiles across various pages. 264 */ 265 public Profiles profiles; 266 267 /** 268 * An map of the profiles to packages. 269 */ 270 public Map<String,PackageDoc[]> profilePackages; 271 272 /** 273 * An array of the packages specified on the command-line merged 274 * with the array of packages that contain the classes specified on the 275 * command-line. The array is sorted. 276 */ 277 public PackageDoc[] packages; 278 279 /** 280 * Constructor. Constructs the message retriever with resource file. 281 */ 282 public Configuration() { 283 message = 284 new MessageRetriever(this, 285 "com.sun.tools.doclets.internal.toolkit.resources.doclets"); 286 excludedDocFileDirs = new HashSet<String>(); 287 excludedQualifiers = new HashSet<String>(); 288 setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH); 289 } 290 291 /** 292 * Return the builder factory for this doclet. 293 * 294 * @return the builder factory for this doclet. 295 */ 296 public BuilderFactory getBuilderFactory() { 297 if (builderFactory == null) { 298 builderFactory = new BuilderFactory(this); 299 } 300 return builderFactory; 301 } 302 303 /** 304 * This method should be defined in all those doclets 305 * which want to inherit from this Configuration. This method 306 * should return the number of arguments to the command line 307 * option (including the option name). For example, 308 * -notimestamp is a single-argument option, so this method would 309 * return 1. 310 * 311 * @param option Command line option under consideration. 312 * @return number of arguments to option (including the 313 * option name). Zero return means option not known. 314 * Negative value means error occurred. 315 */ 316 public int optionLength(String option) { 317 option = option.toLowerCase(); 318 if (option.equals("-author") || 319 option.equals("-docfilessubdirs") || 320 option.equals("-keywords") || 321 option.equals("-linksource") || 322 option.equals("-nocomment") || 323 option.equals("-nodeprecated") || 324 option.equals("-nosince") || 325 option.equals("-notimestamp") || 326 option.equals("-quiet") || 327 option.equals("-xnodate") || 328 option.equals("-version")) { 329 return 1; 330 } else if (option.equals("-d") || 331 option.equals("-docencoding") || 332 option.equals("-encoding") || 333 option.equals("-excludedocfilessubdir") || 334 option.equals("-link") || 335 option.equals("-sourcetab") || 336 option.equals("-noqualifier") || 337 option.equals("-output") || 338 option.equals("-sourcepath") || 339 option.equals("-tag") || 340 option.equals("-taglet") || 341 option.equals("-tagletpath") || 342 option.equals("-xprofilespath")) { 343 return 2; 344 } else if (option.equals("-group") || 345 option.equals("-linkoffline")) { 346 return 3; 347 } else { 348 return -1; // indicate we don't know about it 349 } 350 } 351 352 /** 353 * Perform error checking on the given options. 354 * 355 * @param options the given options to check. 356 * @param reporter the reporter used to report errors. 357 */ 358 public abstract boolean validOptions(String options[][], 359 DocErrorReporter reporter); 360 361 private void initProfiles() throws IOException { 362 profiles = Profiles.read(new File(profilespath)); 363 // Generate profiles documentation only is profilespath is set and if 364 // profiles is not null and profiles count is 1 or more. 365 showProfiles = (!profilespath.isEmpty() && profiles != null && 366 profiles.getProfileCount() > 0); 367 } 368 369 private void initProfilePackages() throws IOException { 370 profilePackages = new HashMap<String,PackageDoc[]>(); 371 ArrayList<PackageDoc> results; 372 Map<String,PackageDoc> packageIndex = new HashMap<String,PackageDoc>(); 373 for (int i = 0; i < packages.length; i++) { 374 PackageDoc pkg = packages[i]; 375 packageIndex.put(pkg.name(), pkg); 376 } 377 for (int i = 1; i < profiles.getProfileCount(); i++) { 378 Set<String> profPkgs = profiles.getPackages(i); 379 results = new ArrayList<PackageDoc>(); 380 for (String packageName : profPkgs) { 381 packageName = packageName.replace("/", "."); 382 PackageDoc profPkg = packageIndex.get(packageName); 383 if (profPkg != null) { 384 results.add(profPkg); 385 } 386 } 387 Collections.sort(results); 388 PackageDoc[] profilePkgs = results.toArray(new PackageDoc[]{}); 389 profilePackages.put(Profile.lookup(i).name, profilePkgs); 390 } 391 } 392 393 private void initPackageArray() { 394 Set<PackageDoc> set = new HashSet<PackageDoc>(Arrays.asList(root.specifiedPackages())); 395 ClassDoc[] classes = root.specifiedClasses(); 396 for (int i = 0; i < classes.length; i++) { 397 set.add(classes[i].containingPackage()); 398 } 399 ArrayList<PackageDoc> results = new ArrayList<PackageDoc>(set); 400 Collections.sort(results); 401 packages = results.toArray(new PackageDoc[] {}); 402 } 403 404 /** 405 * Set the command line options supported by this configuration. 406 * 407 * @param options the two dimensional array of options. 408 */ 409 public void setOptions(String[][] options) { 410 LinkedHashSet<String[]> customTagStrs = new LinkedHashSet<String[]>(); 411 for (int oi = 0; oi < options.length; ++oi) { 412 String[] os = options[oi]; 413 String opt = os[0].toLowerCase(); 414 if (opt.equals("-d")) { 415 destDirName = addTrailingFileSep(os[1]); 416 docFileDestDirName = destDirName; 417 } else if (opt.equals("-docfilessubdirs")) { 418 copydocfilesubdirs = true; 419 } else if (opt.equals("-docencoding")) { 420 docencoding = os[1]; 421 } else if (opt.equals("-encoding")) { 422 encoding = os[1]; 423 } else if (opt.equals("-author")) { 424 showauthor = true; 425 } else if (opt.equals("-nosince")) { 426 nosince = true; 427 } else if (opt.equals("-version")) { 428 showversion = true; 429 } else if (opt.equals("-nodeprecated")) { 430 nodeprecated = true; 431 } else if (opt.equals("-sourcepath")) { 432 sourcepath = os[1]; 433 } else if (opt.equals("-classpath") && 434 sourcepath.length() == 0) { 435 sourcepath = os[1]; 436 } else if (opt.equals("-excludedocfilessubdir")) { 437 addToSet(excludedDocFileDirs, os[1]); 438 } else if (opt.equals("-noqualifier")) { 439 addToSet(excludedQualifiers, os[1]); 440 } else if (opt.equals("-linksource")) { 441 linksource = true; 442 } else if (opt.equals("-sourcetab")) { 443 linksource = true; 444 try { 445 setTabWidth(Integer.parseInt(os[1])); 446 } catch (NumberFormatException e) { 447 //Set to -1 so that warning will be printed 448 //to indicate what is valid argument. 449 sourcetab = -1; 450 } 451 if (sourcetab <= 0) { 452 message.warning("doclet.sourcetab_warning"); 453 setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH); 454 } 455 } else if (opt.equals("-notimestamp")) { 456 notimestamp = true; 457 } else if (opt.equals("-nocomment")) { 458 nocomment = true; 459 } else if (opt.equals("-tag") || opt.equals("-taglet")) { 460 customTagStrs.add(os); 461 } else if (opt.equals("-tagletpath")) { 462 tagletpath = os[1]; 463 } else if (opt.equals("-xprofilespath")) { 464 profilespath = os[1]; 465 } else if (opt.equals("-keywords")) { 466 keywords = true; 467 } else if (opt.equals("-serialwarn")) { 468 serialwarn = true; 469 } else if (opt.equals("-group")) { 470 group.checkPackageGroups(os[1], os[2]); 471 } else if (opt.equals("-link")) { 472 String url = os[1]; 473 extern.link(url, url, root, false); 474 } else if (opt.equals("-linkoffline")) { 475 String url = os[1]; 476 String pkglisturl = os[2]; 477 extern.link(url, pkglisturl, root, true); 478 } 479 } 480 if (sourcepath.length() == 0) { 481 sourcepath = System.getProperty("env.class.path") == null ? "" : 482 System.getProperty("env.class.path"); 483 } 484 if (docencoding == null) { 485 docencoding = encoding; 486 } 487 488 classDocCatalog = new ClassDocCatalog(root.specifiedClasses(), this); 489 initTagletManager(customTagStrs); 490 } 491 492 /** 493 * Set the command line options supported by this configuration. 494 * 495 * @throws DocletAbortException 496 */ 497 public void setOptions() { 498 initPackageArray(); 499 setOptions(root.options()); 500 if (!profilespath.isEmpty()) { 501 try { 502 initProfiles(); 503 initProfilePackages(); 504 } catch (Exception e) { 505 throw new DocletAbortException(); 506 } 507 } 508 setSpecificDocletOptions(root.options()); 509 } 510 511 512 /** 513 * Initialize the taglet manager. The strings to initialize the simple custom tags should 514 * be in the following format: "[tag name]:[location str]:[heading]". 515 * @param customTagStrs the set two dimensional arrays of strings. These arrays contain 516 * either -tag or -taglet arguments. 517 */ 518 private void initTagletManager(Set<String[]> customTagStrs) { 519 tagletManager = tagletManager == null ? 520 new TagletManager(nosince, showversion, showauthor, message) : 521 tagletManager; 522 String[] args; 523 for (Iterator<String[]> it = customTagStrs.iterator(); it.hasNext(); ) { 524 args = it.next(); 525 if (args[0].equals("-taglet")) { 526 tagletManager.addCustomTag(args[1], getFileManager(), tagletpath); 527 continue; 528 } 529 String[] tokens = tokenize(args[1], 530 TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3); 531 if (tokens.length == 1) { 532 String tagName = args[1]; 533 if (tagletManager.isKnownCustomTag(tagName)) { 534 //reorder a standard tag 535 tagletManager.addNewSimpleCustomTag(tagName, null, ""); 536 } else { 537 //Create a simple tag with the heading that has the same name as the tag. 538 StringBuilder heading = new StringBuilder(tagName + ":"); 539 heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0))); 540 tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a"); 541 } 542 } else if (tokens.length == 2) { 543 //Add simple taglet without heading, probably to excluding it in the output. 544 tagletManager.addNewSimpleCustomTag(tokens[0], tokens[1], ""); 545 } else if (tokens.length >= 3) { 546 tagletManager.addNewSimpleCustomTag(tokens[0], tokens[2], tokens[1]); 547 } else { 548 message.error("doclet.Error_invalid_custom_tag_argument", args[1]); 549 } 550 } 551 } 552 553 /** 554 * Given a string, return an array of tokens. The separator can be escaped 555 * with the '\' character. The '\' character may also be escaped by the 556 * '\' character. 557 * 558 * @param s the string to tokenize. 559 * @param separator the separator char. 560 * @param maxTokens the maximum number of tokens returned. If the 561 * max is reached, the remaining part of s is appended 562 * to the end of the last token. 563 * 564 * @return an array of tokens. 565 */ 566 private String[] tokenize(String s, char separator, int maxTokens) { 567 List<String> tokens = new ArrayList<String>(); 568 StringBuilder token = new StringBuilder (); 569 boolean prevIsEscapeChar = false; 570 for (int i = 0; i < s.length(); i += Character.charCount(i)) { 571 int currentChar = s.codePointAt(i); 572 if (prevIsEscapeChar) { 573 // Case 1: escaped character 574 token.appendCodePoint(currentChar); 575 prevIsEscapeChar = false; 576 } else if (currentChar == separator && tokens.size() < maxTokens-1) { 577 // Case 2: separator 578 tokens.add(token.toString()); 579 token = new StringBuilder(); 580 } else if (currentChar == '\\') { 581 // Case 3: escape character 582 prevIsEscapeChar = true; 583 } else { 584 // Case 4: regular character 585 token.appendCodePoint(currentChar); 586 } 587 } 588 if (token.length() > 0) { 589 tokens.add(token.toString()); 590 } 591 return tokens.toArray(new String[] {}); 592 } 593 594 private void addToSet(Set<String> s, String str){ 595 StringTokenizer st = new StringTokenizer(str, ":"); 596 String current; 597 while(st.hasMoreTokens()){ 598 current = st.nextToken(); 599 s.add(current); 600 } 601 } 602 603 /** 604 * Add a trailing file separator, if not found. Remove superfluous 605 * file separators if any. Preserve the front double file separator for 606 * UNC paths. 607 * 608 * @param path Path under consideration. 609 * @return String Properly constructed path string. 610 */ 611 public static String addTrailingFileSep(String path) { 612 String fs = System.getProperty("file.separator"); 613 String dblfs = fs + fs; 614 int indexDblfs; 615 while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) { 616 path = path.substring(0, indexDblfs) + 617 path.substring(indexDblfs + fs.length()); 618 } 619 if (!path.endsWith(fs)) 620 path += fs; 621 return path; 622 } 623 624 /** 625 * This checks for the validity of the options used by the user. 626 * This works exactly like 627 * {@link com.sun.javadoc.Doclet#validOptions(String[][], 628 * DocErrorReporter)}. This will validate the options which are shared 629 * by our doclets. For example, this method will flag an error using 630 * the DocErrorReporter if user has used "-nohelp" and "-helpfile" option 631 * together. 632 * 633 * @param options options used on the command line. 634 * @param reporter used to report errors. 635 * @return true if all the options are valid. 636 */ 637 public boolean generalValidOptions(String options[][], 638 DocErrorReporter reporter) { 639 boolean docencodingfound = false; 640 String encoding = ""; 641 for (int oi = 0; oi < options.length; oi++) { 642 String[] os = options[oi]; 643 String opt = os[0].toLowerCase(); 644 if (opt.equals("-d")) { 645 String destdirname = addTrailingFileSep(os[1]); 646 DocFile destDir = DocFile.createFileForDirectory(this, destdirname); 647 if (!destDir.exists()) { 648 //Create the output directory (in case it doesn't exist yet) 649 reporter.printNotice(getText("doclet.dest_dir_create", 650 destdirname)); 651 destDir.mkdirs(); 652 } else if (!destDir.isDirectory()) { 653 reporter.printError(getText( 654 "doclet.destination_directory_not_directory_0", 655 destDir.getPath())); 656 return false; 657 } else if (!destDir.canWrite()) { 658 reporter.printError(getText( 659 "doclet.destination_directory_not_writable_0", 660 destDir.getPath())); 661 return false; 662 } 663 } else if (opt.equals("-docencoding")) { 664 docencodingfound = true; 665 if (!checkOutputFileEncoding(os[1], reporter)) { 666 return false; 667 } 668 } else if (opt.equals("-encoding")) { 669 encoding = os[1]; 670 } 671 } 672 if (!docencodingfound && encoding.length() > 0) { 673 if (!checkOutputFileEncoding(encoding, reporter)) { 674 return false; 675 } 676 } 677 return true; 678 } 679 680 /** 681 * Check the validity of the given Source or Output File encoding on this 682 * platform. 683 * 684 * @param docencoding output file encoding. 685 * @param reporter used to report errors. 686 */ 687 private boolean checkOutputFileEncoding(String docencoding, 688 DocErrorReporter reporter) { 689 OutputStream ost= new ByteArrayOutputStream(); 690 OutputStreamWriter osw = null; 691 try { 692 osw = new OutputStreamWriter(ost, docencoding); 693 } catch (UnsupportedEncodingException exc) { 694 reporter.printError(getText("doclet.Encoding_not_supported", 695 docencoding)); 696 return false; 697 } finally { 698 try { 699 if (osw != null) { 700 osw.close(); 701 } 702 } catch (IOException exc) { 703 } 704 } 705 return true; 706 } 707 708 /** 709 * Return true if the given doc-file subdirectory should be excluded and 710 * false otherwise. 711 * @param docfilesubdir the doc-files subdirectory to check. 712 */ 713 public boolean shouldExcludeDocFileDir(String docfilesubdir){ 714 if (excludedDocFileDirs.contains(docfilesubdir)) { 715 return true; 716 } else { 717 return false; 718 } 719 } 720 721 /** 722 * Return true if the given qualifier should be excluded and false otherwise. 723 * @param qualifier the qualifier to check. 724 */ 725 public boolean shouldExcludeQualifier(String qualifier){ 726 if (excludedQualifiers.contains("all") || 727 excludedQualifiers.contains(qualifier) || 728 excludedQualifiers.contains(qualifier + ".*")) { 729 return true; 730 } else { 731 int index = -1; 732 while ((index = qualifier.indexOf(".", index + 1)) != -1) { 733 if (excludedQualifiers.contains(qualifier.substring(0, index + 1) + "*")) { 734 return true; 735 } 736 } 737 return false; 738 } 739 } 740 741 /** 742 * Return the qualified name of the <code>ClassDoc</code> if it's qualifier is not excluded. Otherwise, 743 * return the unqualified <code>ClassDoc</code> name. 744 * @param cd the <code>ClassDoc</code> to check. 745 */ 746 public String getClassName(ClassDoc cd) { 747 PackageDoc pd = cd.containingPackage(); 748 if (pd != null && shouldExcludeQualifier(cd.containingPackage().name())) { 749 return cd.name(); 750 } else { 751 return cd.qualifiedName(); 752 } 753 } 754 755 public String getText(String key) { 756 try { 757 //Check the doclet specific properties file. 758 return getDocletSpecificMsg().getText(key); 759 } catch (Exception e) { 760 //Check the shared properties file. 761 return message.getText(key); 762 } 763 } 764 765 public String getText(String key, String a1) { 766 try { 767 //Check the doclet specific properties file. 768 return getDocletSpecificMsg().getText(key, a1); 769 } catch (Exception e) { 770 //Check the shared properties file. 771 return message.getText(key, a1); 772 } 773 } 774 775 public String getText(String key, String a1, String a2) { 776 try { 777 //Check the doclet specific properties file. 778 return getDocletSpecificMsg().getText(key, a1, a2); 779 } catch (Exception e) { 780 //Check the shared properties file. 781 return message.getText(key, a1, a2); 782 } 783 } 784 785 public String getText(String key, String a1, String a2, String a3) { 786 try { 787 //Check the doclet specific properties file. 788 return getDocletSpecificMsg().getText(key, a1, a2, a3); 789 } catch (Exception e) { 790 //Check the shared properties file. 791 return message.getText(key, a1, a2, a3); 792 } 793 } 794 795 /** 796 * Return true if the ClassDoc element is getting documented, depending upon 797 * -nodeprecated option and the deprecation information. Return true if 798 * -nodeprecated is not used. Return false if -nodeprecated is used and if 799 * either ClassDoc element is deprecated or the containing package is deprecated. 800 * 801 * @param cd the ClassDoc for which the page generation is checked 802 */ 803 public boolean isGeneratedDoc(ClassDoc cd) { 804 if (!nodeprecated) { 805 return true; 806 } 807 return !(Util.isDeprecated(cd) || Util.isDeprecated(cd.containingPackage())); 808 } 809 810 /** 811 * Return the doclet specific instance of a writer factory. 812 * @return the {@link WriterFactory} for the doclet. 813 */ 814 public abstract WriterFactory getWriterFactory(); 815 816 /** 817 * Return the input stream to the builder XML. 818 * 819 * @return the input steam to the builder XML. 820 * @throws FileNotFoundException when the given XML file cannot be found. 821 */ 822 public InputStream getBuilderXML() throws IOException { 823 return builderXMLPath == null ? 824 Configuration.class.getResourceAsStream(DEFAULT_BUILDER_XML) : 825 DocFile.createFileForInput(this, builderXMLPath).openInputStream(); 826 } 827 828 /** 829 * Return the Locale for this document. 830 */ 831 public abstract Locale getLocale(); 832 833 /** 834 * Return the current file manager. 835 */ 836 public abstract JavaFileManager getFileManager(); 837 838 /** 839 * Return the comparator that will be used to sort member documentation. 840 * To no do any sorting, return null. 841 * 842 * @return the {@link java.util.Comparator} used to sort members. 843 */ 844 public abstract Comparator<ProgramElementDoc> getMemberComparator(); 845 846 private void setTabWidth(int n) { 847 sourcetab = n; 848 tabSpaces = String.format("%" + n + "s", ""); 849 } 850 }