Sat, 07 Nov 2020 10:30:02 +0800
Added tag mips-jdk8u275-b01 for changeset eb6ee6a5f2fe
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 */
26 package com.sun.tools.doclets.internal.toolkit;
28 import java.io.*;
29 import java.util.*;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32 import javax.tools.JavaFileManager;
34 import com.sun.javadoc.*;
35 import com.sun.tools.javac.sym.Profiles;
36 import com.sun.tools.javac.jvm.Profile;
37 import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory;
38 import com.sun.tools.doclets.internal.toolkit.taglets.*;
39 import com.sun.tools.doclets.internal.toolkit.util.*;
40 import com.sun.tools.javac.util.StringUtils;
42 /**
43 * Configure the output based on the options. Doclets should sub-class
44 * Configuration, to configure and add their own options. This class contains
45 * all user options which are supported by the 1.1 doclet and the standard
46 * doclet.
47 *
48 * <p><b>This is NOT part of any supported API.
49 * If you write code that depends on this, you do so at your own risk.
50 * This code and its internal interfaces are subject to change or
51 * deletion without notice.</b>
52 *
53 * @author Robert Field.
54 * @author Atul Dambalkar.
55 * @author Jamie Ho
56 */
57 public abstract class Configuration {
59 /**
60 * Exception used to report a problem during setOptions.
61 */
62 public static class Fault extends Exception {
63 private static final long serialVersionUID = 0;
65 Fault(String msg) {
66 super(msg);
67 }
69 Fault(String msg, Exception cause) {
70 super(msg, cause);
71 }
72 }
74 /**
75 * The factory for builders.
76 */
77 protected BuilderFactory builderFactory;
79 /**
80 * The taglet manager.
81 */
82 public TagletManager tagletManager;
84 /**
85 * The path to the builder XML input file.
86 */
87 public String builderXMLPath;
89 /**
90 * The default path to the builder XML.
91 */
92 private static final String DEFAULT_BUILDER_XML = "resources/doclet.xml";
94 /**
95 * The path to Taglets
96 */
97 public String tagletpath = "";
99 /**
100 * This is true if option "-serialwarn" is used. Defualt value is false to
101 * suppress excessive warnings about serial tag.
102 */
103 public boolean serialwarn = false;
105 /**
106 * The specified amount of space between tab stops.
107 */
108 public int sourcetab;
110 public String tabSpaces;
112 /**
113 * True if we should generate browsable sources.
114 */
115 public boolean linksource = false;
117 /**
118 * True if command line option "-nosince" is used. Default value is
119 * false.
120 */
121 public boolean nosince = false;
123 /**
124 * True if we should recursively copy the doc-file subdirectories
125 */
126 public boolean copydocfilesubdirs = false;
128 /**
129 * The META charset tag used for cross-platform viewing.
130 */
131 public String charset = "";
133 /**
134 * True if user wants to add member names as meta keywords.
135 * Set to false because meta keywords are ignored in general
136 * by most Internet search engines.
137 */
138 public boolean keywords = false;
140 /**
141 * The meta tag keywords instance.
142 */
143 public final MetaKeywords metakeywords = new MetaKeywords(this);
145 /**
146 * The list of doc-file subdirectories to exclude
147 */
148 protected Set<String> excludedDocFileDirs;
150 /**
151 * The list of qualifiers to exclude
152 */
153 protected Set<String> excludedQualifiers;
155 /**
156 * The Root of the generated Program Structure from the Doclet API.
157 */
158 public RootDoc root;
160 /**
161 * Destination directory name, in which doclet will generate the entire
162 * documentation. Default is current directory.
163 */
164 public String destDirName = "";
166 /**
167 * Destination directory name, in which doclet will copy the doc-files to.
168 */
169 public String docFileDestDirName = "";
171 /**
172 * Encoding for this document. Default is default encoding for this
173 * platform.
174 */
175 public String docencoding = null;
177 /**
178 * True if user wants to suppress descriptions and tags.
179 */
180 public boolean nocomment = false;
182 /**
183 * Encoding for this document. Default is default encoding for this
184 * platform.
185 */
186 public String encoding = null;
188 /**
189 * Generate author specific information for all the classes if @author
190 * tag is used in the doc comment and if -author option is used.
191 * <code>showauthor</code> is set to true if -author option is used.
192 * Default is don't show author information.
193 */
194 public boolean showauthor = false;
196 /**
197 * Generate documentation for JavaFX getters and setters automatically
198 * by copying it from the appropriate property definition.
199 */
200 public boolean javafx = false;
202 /**
203 * Generate version specific information for the all the classes
204 * if @version tag is used in the doc comment and if -version option is
205 * used. <code>showversion</code> is set to true if -version option is
206 * used.Default is don't show version information.
207 */
208 public boolean showversion = false;
210 /**
211 * Sourcepath from where to read the source files. Default is classpath.
212 *
213 */
214 public String sourcepath = "";
216 /**
217 * Argument for command line option "-Xprofilespath".
218 */
219 public String profilespath = "";
221 /**
222 * Generate profiles documentation if profilespath is set and valid profiles
223 * are present.
224 */
225 public boolean showProfiles = false;
227 /**
228 * Don't generate deprecated API information at all, if -nodeprecated
229 * option is used. <code>nodepracted</code> is set to true if
230 * -nodeprecated option is used. Default is generate deprected API
231 * information.
232 */
233 public boolean nodeprecated = false;
235 /**
236 * The catalog of classes specified on the command-line
237 */
238 public ClassDocCatalog classDocCatalog;
240 /**
241 * Message Retriever for the doclet, to retrieve message from the resource
242 * file for this Configuration, which is common for 1.1 and standard
243 * doclets.
244 *
245 * TODO: Make this private!!!
246 */
247 public MessageRetriever message = null;
249 /**
250 * True if user wants to suppress time stamp in output.
251 * Default is false.
252 */
253 public boolean notimestamp= false;
255 /**
256 * The package grouping instance.
257 */
258 public final Group group = new Group(this);
260 /**
261 * The tracker of external package links.
262 */
263 public final Extern extern = new Extern(this);
265 /**
266 * Return the build date for the doclet.
267 */
268 public abstract String getDocletSpecificBuildDate();
270 /**
271 * This method should be defined in all those doclets(configurations),
272 * which want to derive themselves from this Configuration. This method
273 * can be used to set its own command line options.
274 *
275 * @param options The array of option names and values.
276 * @throws DocletAbortException
277 */
278 public abstract void setSpecificDocletOptions(String[][] options) throws Fault;
280 /**
281 * Return the doclet specific {@link MessageRetriever}
282 * @return the doclet specific MessageRetriever.
283 */
284 public abstract MessageRetriever getDocletSpecificMsg();
286 /**
287 * A profiles object used to access profiles across various pages.
288 */
289 public Profiles profiles;
291 /**
292 * An map of the profiles to packages.
293 */
294 public Map<String,PackageDoc[]> profilePackages;
296 /**
297 * An array of the packages specified on the command-line merged
298 * with the array of packages that contain the classes specified on the
299 * command-line. The array is sorted.
300 */
301 public PackageDoc[] packages;
303 /**
304 * Constructor. Constructs the message retriever with resource file.
305 */
306 public Configuration() {
307 message =
308 new MessageRetriever(this,
309 "com.sun.tools.doclets.internal.toolkit.resources.doclets");
310 excludedDocFileDirs = new HashSet<String>();
311 excludedQualifiers = new HashSet<String>();
312 setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
313 }
315 /**
316 * Return the builder factory for this doclet.
317 *
318 * @return the builder factory for this doclet.
319 */
320 public BuilderFactory getBuilderFactory() {
321 if (builderFactory == null) {
322 builderFactory = new BuilderFactory(this);
323 }
324 return builderFactory;
325 }
327 /**
328 * This method should be defined in all those doclets
329 * which want to inherit from this Configuration. This method
330 * should return the number of arguments to the command line
331 * option (including the option name). For example,
332 * -notimestamp is a single-argument option, so this method would
333 * return 1.
334 *
335 * @param option Command line option under consideration.
336 * @return number of arguments to option (including the
337 * option name). Zero return means option not known.
338 * Negative value means error occurred.
339 */
340 public int optionLength(String option) {
341 option = StringUtils.toLowerCase(option);
342 if (option.equals("-author") ||
343 option.equals("-docfilessubdirs") ||
344 option.equals("-javafx") ||
345 option.equals("-keywords") ||
346 option.equals("-linksource") ||
347 option.equals("-nocomment") ||
348 option.equals("-nodeprecated") ||
349 option.equals("-nosince") ||
350 option.equals("-notimestamp") ||
351 option.equals("-quiet") ||
352 option.equals("-xnodate") ||
353 option.equals("-version")) {
354 return 1;
355 } else if (option.equals("-d") ||
356 option.equals("-docencoding") ||
357 option.equals("-encoding") ||
358 option.equals("-excludedocfilessubdir") ||
359 option.equals("-link") ||
360 option.equals("-sourcetab") ||
361 option.equals("-noqualifier") ||
362 option.equals("-output") ||
363 option.equals("-sourcepath") ||
364 option.equals("-tag") ||
365 option.equals("-taglet") ||
366 option.equals("-tagletpath") ||
367 option.equals("-xprofilespath")) {
368 return 2;
369 } else if (option.equals("-group") ||
370 option.equals("-linkoffline")) {
371 return 3;
372 } else {
373 return -1; // indicate we don't know about it
374 }
375 }
377 /**
378 * Perform error checking on the given options.
379 *
380 * @param options the given options to check.
381 * @param reporter the reporter used to report errors.
382 */
383 public abstract boolean validOptions(String options[][],
384 DocErrorReporter reporter);
386 private void initProfiles() throws IOException {
387 if (profilespath.isEmpty())
388 return;
390 profiles = Profiles.read(new File(profilespath));
392 // Group the packages to be documented by the lowest profile (if any)
393 // in which each appears
394 Map<Profile, List<PackageDoc>> interimResults =
395 new EnumMap<Profile, List<PackageDoc>>(Profile.class);
396 for (Profile p: Profile.values())
397 interimResults.put(p, new ArrayList<PackageDoc>());
399 for (PackageDoc pkg: packages) {
400 if (nodeprecated && Util.isDeprecated(pkg)) {
401 continue;
402 }
403 // the getProfile method takes a type name, not a package name,
404 // but isn't particularly fussy about the simple name -- so just use *
405 int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*");
406 Profile p = Profile.lookup(i);
407 if (p != null) {
408 List<PackageDoc> pkgs = interimResults.get(p);
409 pkgs.add(pkg);
410 }
411 }
413 // Build the profilePackages structure used by the doclet
414 profilePackages = new HashMap<String,PackageDoc[]>();
415 List<PackageDoc> prev = Collections.<PackageDoc>emptyList();
416 int size;
417 for (Map.Entry<Profile,List<PackageDoc>> e: interimResults.entrySet()) {
418 Profile p = e.getKey();
419 List<PackageDoc> pkgs = e.getValue();
420 pkgs.addAll(prev); // each profile contains all lower profiles
421 Collections.sort(pkgs);
422 size = pkgs.size();
423 // For a profile, if there are no packages to be documented, do not add
424 // it to profilePackages map.
425 if (size > 0)
426 profilePackages.put(p.name, pkgs.toArray(new PackageDoc[pkgs.size()]));
427 prev = pkgs;
428 }
430 // Generate profiles documentation if any profile contains any
431 // of the packages to be documented.
432 showProfiles = !prev.isEmpty();
433 }
435 private void initPackageArray() {
436 Set<PackageDoc> set = new HashSet<PackageDoc>(Arrays.asList(root.specifiedPackages()));
437 ClassDoc[] classes = root.specifiedClasses();
438 for (int i = 0; i < classes.length; i++) {
439 set.add(classes[i].containingPackage());
440 }
441 ArrayList<PackageDoc> results = new ArrayList<PackageDoc>(set);
442 Collections.sort(results);
443 packages = results.toArray(new PackageDoc[] {});
444 }
446 /**
447 * Set the command line options supported by this configuration.
448 *
449 * @param options the two dimensional array of options.
450 */
451 public void setOptions(String[][] options) throws Fault {
452 LinkedHashSet<String[]> customTagStrs = new LinkedHashSet<String[]>();
454 // Some options, specifically -link and -linkoffline, require that
455 // the output directory has already been created: so do that first.
456 for (int oi = 0; oi < options.length; ++oi) {
457 String[] os = options[oi];
458 String opt = StringUtils.toLowerCase(os[0]);
459 if (opt.equals("-d")) {
460 destDirName = addTrailingFileSep(os[1]);
461 docFileDestDirName = destDirName;
462 ensureOutputDirExists();
463 break;
464 }
465 }
467 for (int oi = 0; oi < options.length; ++oi) {
468 String[] os = options[oi];
469 String opt = StringUtils.toLowerCase(os[0]);
470 if (opt.equals("-docfilessubdirs")) {
471 copydocfilesubdirs = true;
472 } else if (opt.equals("-docencoding")) {
473 docencoding = os[1];
474 } else if (opt.equals("-encoding")) {
475 encoding = os[1];
476 } else if (opt.equals("-author")) {
477 showauthor = true;
478 } else if (opt.equals("-javafx")) {
479 javafx = true;
480 } else if (opt.equals("-nosince")) {
481 nosince = true;
482 } else if (opt.equals("-version")) {
483 showversion = true;
484 } else if (opt.equals("-nodeprecated")) {
485 nodeprecated = true;
486 } else if (opt.equals("-sourcepath")) {
487 sourcepath = os[1];
488 } else if ((opt.equals("-classpath") || opt.equals("-cp")) &&
489 sourcepath.length() == 0) {
490 sourcepath = os[1];
491 } else if (opt.equals("-excludedocfilessubdir")) {
492 addToSet(excludedDocFileDirs, os[1]);
493 } else if (opt.equals("-noqualifier")) {
494 addToSet(excludedQualifiers, os[1]);
495 } else if (opt.equals("-linksource")) {
496 linksource = true;
497 } else if (opt.equals("-sourcetab")) {
498 linksource = true;
499 try {
500 setTabWidth(Integer.parseInt(os[1]));
501 } catch (NumberFormatException e) {
502 //Set to -1 so that warning will be printed
503 //to indicate what is valid argument.
504 sourcetab = -1;
505 }
506 if (sourcetab <= 0) {
507 message.warning("doclet.sourcetab_warning");
508 setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
509 }
510 } else if (opt.equals("-notimestamp")) {
511 notimestamp = true;
512 } else if (opt.equals("-nocomment")) {
513 nocomment = true;
514 } else if (opt.equals("-tag") || opt.equals("-taglet")) {
515 customTagStrs.add(os);
516 } else if (opt.equals("-tagletpath")) {
517 tagletpath = os[1];
518 } else if (opt.equals("-xprofilespath")) {
519 profilespath = os[1];
520 } else if (opt.equals("-keywords")) {
521 keywords = true;
522 } else if (opt.equals("-serialwarn")) {
523 serialwarn = true;
524 } else if (opt.equals("-group")) {
525 group.checkPackageGroups(os[1], os[2]);
526 } else if (opt.equals("-link")) {
527 String url = os[1];
528 extern.link(url, url, root, false);
529 } else if (opt.equals("-linkoffline")) {
530 String url = os[1];
531 String pkglisturl = os[2];
532 extern.link(url, pkglisturl, root, true);
533 }
534 }
535 if (sourcepath.length() == 0) {
536 sourcepath = System.getProperty("env.class.path") == null ? "" :
537 System.getProperty("env.class.path");
538 }
539 if (docencoding == null) {
540 docencoding = encoding;
541 }
543 classDocCatalog = new ClassDocCatalog(root.specifiedClasses(), this);
544 initTagletManager(customTagStrs);
545 }
547 /**
548 * Set the command line options supported by this configuration.
549 *
550 * @throws DocletAbortException
551 */
552 public void setOptions() throws Fault {
553 initPackageArray();
554 setOptions(root.options());
555 try {
556 initProfiles();
557 } catch (Exception e) {
558 throw new DocletAbortException(e);
559 }
560 setSpecificDocletOptions(root.options());
561 }
563 private void ensureOutputDirExists() throws Fault {
564 DocFile destDir = DocFile.createFileForDirectory(this, destDirName);
565 if (!destDir.exists()) {
566 //Create the output directory (in case it doesn't exist yet)
567 root.printNotice(getText("doclet.dest_dir_create", destDirName));
568 destDir.mkdirs();
569 } else if (!destDir.isDirectory()) {
570 throw new Fault(getText(
571 "doclet.destination_directory_not_directory_0",
572 destDir.getPath()));
573 } else if (!destDir.canWrite()) {
574 throw new Fault(getText(
575 "doclet.destination_directory_not_writable_0",
576 destDir.getPath()));
577 }
578 }
581 /**
582 * Initialize the taglet manager. The strings to initialize the simple custom tags should
583 * be in the following format: "[tag name]:[location str]:[heading]".
584 * @param customTagStrs the set two dimensional arrays of strings. These arrays contain
585 * either -tag or -taglet arguments.
586 */
587 private void initTagletManager(Set<String[]> customTagStrs) {
588 tagletManager = tagletManager == null ?
589 new TagletManager(nosince, showversion, showauthor, javafx, message) :
590 tagletManager;
591 String[] args;
592 for (Iterator<String[]> it = customTagStrs.iterator(); it.hasNext(); ) {
593 args = it.next();
594 if (args[0].equals("-taglet")) {
595 tagletManager.addCustomTag(args[1], getFileManager(), tagletpath);
596 continue;
597 }
598 String[] tokens = tokenize(args[1],
599 TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
600 if (tokens.length == 1) {
601 String tagName = args[1];
602 if (tagletManager.isKnownCustomTag(tagName)) {
603 //reorder a standard tag
604 tagletManager.addNewSimpleCustomTag(tagName, null, "");
605 } else {
606 //Create a simple tag with the heading that has the same name as the tag.
607 StringBuilder heading = new StringBuilder(tagName + ":");
608 heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
609 tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
610 }
611 } else if (tokens.length == 2) {
612 //Add simple taglet without heading, probably to excluding it in the output.
613 tagletManager.addNewSimpleCustomTag(tokens[0], tokens[1], "");
614 } else if (tokens.length >= 3) {
615 tagletManager.addNewSimpleCustomTag(tokens[0], tokens[2], tokens[1]);
616 } else {
617 message.error("doclet.Error_invalid_custom_tag_argument", args[1]);
618 }
619 }
620 }
622 /**
623 * Given a string, return an array of tokens. The separator can be escaped
624 * with the '\' character. The '\' character may also be escaped by the
625 * '\' character.
626 *
627 * @param s the string to tokenize.
628 * @param separator the separator char.
629 * @param maxTokens the maximum number of tokens returned. If the
630 * max is reached, the remaining part of s is appended
631 * to the end of the last token.
632 *
633 * @return an array of tokens.
634 */
635 private String[] tokenize(String s, char separator, int maxTokens) {
636 List<String> tokens = new ArrayList<String>();
637 StringBuilder token = new StringBuilder ();
638 boolean prevIsEscapeChar = false;
639 for (int i = 0; i < s.length(); i += Character.charCount(i)) {
640 int currentChar = s.codePointAt(i);
641 if (prevIsEscapeChar) {
642 // Case 1: escaped character
643 token.appendCodePoint(currentChar);
644 prevIsEscapeChar = false;
645 } else if (currentChar == separator && tokens.size() < maxTokens-1) {
646 // Case 2: separator
647 tokens.add(token.toString());
648 token = new StringBuilder();
649 } else if (currentChar == '\\') {
650 // Case 3: escape character
651 prevIsEscapeChar = true;
652 } else {
653 // Case 4: regular character
654 token.appendCodePoint(currentChar);
655 }
656 }
657 if (token.length() > 0) {
658 tokens.add(token.toString());
659 }
660 return tokens.toArray(new String[] {});
661 }
663 private void addToSet(Set<String> s, String str){
664 StringTokenizer st = new StringTokenizer(str, ":");
665 String current;
666 while(st.hasMoreTokens()){
667 current = st.nextToken();
668 s.add(current);
669 }
670 }
672 /**
673 * Add a trailing file separator, if not found. Remove superfluous
674 * file separators if any. Preserve the front double file separator for
675 * UNC paths.
676 *
677 * @param path Path under consideration.
678 * @return String Properly constructed path string.
679 */
680 public static String addTrailingFileSep(String path) {
681 String fs = System.getProperty("file.separator");
682 String dblfs = fs + fs;
683 int indexDblfs;
684 while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
685 path = path.substring(0, indexDblfs) +
686 path.substring(indexDblfs + fs.length());
687 }
688 if (!path.endsWith(fs))
689 path += fs;
690 return path;
691 }
693 /**
694 * This checks for the validity of the options used by the user.
695 * This works exactly like
696 * {@link com.sun.javadoc.Doclet#validOptions(String[][],
697 * DocErrorReporter)}. This will validate the options which are shared
698 * by our doclets. For example, this method will flag an error using
699 * the DocErrorReporter if user has used "-nohelp" and "-helpfile" option
700 * together.
701 *
702 * @param options options used on the command line.
703 * @param reporter used to report errors.
704 * @return true if all the options are valid.
705 */
706 public boolean generalValidOptions(String options[][],
707 DocErrorReporter reporter) {
708 boolean docencodingfound = false;
709 String encoding = "";
710 for (int oi = 0; oi < options.length; oi++) {
711 String[] os = options[oi];
712 String opt = StringUtils.toLowerCase(os[0]);
713 if (opt.equals("-docencoding")) {
714 docencodingfound = true;
715 if (!checkOutputFileEncoding(os[1], reporter)) {
716 return false;
717 }
718 } else if (opt.equals("-encoding")) {
719 encoding = os[1];
720 }
721 }
722 if (!docencodingfound && encoding.length() > 0) {
723 if (!checkOutputFileEncoding(encoding, reporter)) {
724 return false;
725 }
726 }
727 return true;
728 }
730 /**
731 * Check the validity of the given profile. Return false if there are no
732 * valid packages to be documented for the profile.
733 *
734 * @param profileName the profile that needs to be validated.
735 * @return true if the profile has valid packages to be documented.
736 */
737 public boolean shouldDocumentProfile(String profileName) {
738 return profilePackages.containsKey(profileName);
739 }
741 /**
742 * Check the validity of the given Source or Output File encoding on this
743 * platform.
744 *
745 * @param docencoding output file encoding.
746 * @param reporter used to report errors.
747 */
748 private boolean checkOutputFileEncoding(String docencoding,
749 DocErrorReporter reporter) {
750 OutputStream ost= new ByteArrayOutputStream();
751 OutputStreamWriter osw = null;
752 try {
753 osw = new OutputStreamWriter(ost, docencoding);
754 } catch (UnsupportedEncodingException exc) {
755 reporter.printError(getText("doclet.Encoding_not_supported",
756 docencoding));
757 return false;
758 } finally {
759 try {
760 if (osw != null) {
761 osw.close();
762 }
763 } catch (IOException exc) {
764 }
765 }
766 return true;
767 }
769 /**
770 * Return true if the given doc-file subdirectory should be excluded and
771 * false otherwise.
772 * @param docfilesubdir the doc-files subdirectory to check.
773 */
774 public boolean shouldExcludeDocFileDir(String docfilesubdir){
775 if (excludedDocFileDirs.contains(docfilesubdir)) {
776 return true;
777 } else {
778 return false;
779 }
780 }
782 /**
783 * Return true if the given qualifier should be excluded and false otherwise.
784 * @param qualifier the qualifier to check.
785 */
786 public boolean shouldExcludeQualifier(String qualifier){
787 if (excludedQualifiers.contains("all") ||
788 excludedQualifiers.contains(qualifier) ||
789 excludedQualifiers.contains(qualifier + ".*")) {
790 return true;
791 } else {
792 int index = -1;
793 while ((index = qualifier.indexOf(".", index + 1)) != -1) {
794 if (excludedQualifiers.contains(qualifier.substring(0, index + 1) + "*")) {
795 return true;
796 }
797 }
798 return false;
799 }
800 }
802 /**
803 * Return the qualified name of the <code>ClassDoc</code> if it's qualifier is not excluded. Otherwise,
804 * return the unqualified <code>ClassDoc</code> name.
805 * @param cd the <code>ClassDoc</code> to check.
806 */
807 public String getClassName(ClassDoc cd) {
808 PackageDoc pd = cd.containingPackage();
809 if (pd != null && shouldExcludeQualifier(cd.containingPackage().name())) {
810 return cd.name();
811 } else {
812 return cd.qualifiedName();
813 }
814 }
816 public String getText(String key) {
817 try {
818 //Check the doclet specific properties file.
819 return getDocletSpecificMsg().getText(key);
820 } catch (Exception e) {
821 //Check the shared properties file.
822 return message.getText(key);
823 }
824 }
826 public String getText(String key, String a1) {
827 try {
828 //Check the doclet specific properties file.
829 return getDocletSpecificMsg().getText(key, a1);
830 } catch (Exception e) {
831 //Check the shared properties file.
832 return message.getText(key, a1);
833 }
834 }
836 public String getText(String key, String a1, String a2) {
837 try {
838 //Check the doclet specific properties file.
839 return getDocletSpecificMsg().getText(key, a1, a2);
840 } catch (Exception e) {
841 //Check the shared properties file.
842 return message.getText(key, a1, a2);
843 }
844 }
846 public String getText(String key, String a1, String a2, String a3) {
847 try {
848 //Check the doclet specific properties file.
849 return getDocletSpecificMsg().getText(key, a1, a2, a3);
850 } catch (Exception e) {
851 //Check the shared properties file.
852 return message.getText(key, a1, a2, a3);
853 }
854 }
856 public abstract Content newContent();
858 /**
859 * Get the configuration string as a content.
860 *
861 * @param key the key to look for in the configuration file
862 * @return a content tree for the text
863 */
864 public Content getResource(String key) {
865 Content c = newContent();
866 c.addContent(getText(key));
867 return c;
868 }
870 /**
871 * Get the configuration string as a content.
872 *
873 * @param key the key to look for in the configuration file
874 * @param o string or content argument added to configuration text
875 * @return a content tree for the text
876 */
877 public Content getResource(String key, Object o) {
878 return getResource(key, o, null, null);
879 }
881 /**
882 * Get the configuration string as a content.
883 *
884 * @param key the key to look for in the configuration file
885 * @param o string or content argument added to configuration text
886 * @return a content tree for the text
887 */
888 public Content getResource(String key, Object o1, Object o2) {
889 return getResource(key, o1, o2, null);
890 }
892 /**
893 * Get the configuration string as a content.
894 *
895 * @param key the key to look for in the configuration file
896 * @param o1 string or content argument added to configuration text
897 * @param o2 string or content argument added to configuration text
898 * @return a content tree for the text
899 */
900 public Content getResource(String key, Object o0, Object o1, Object o2) {
901 Content c = newContent();
902 Pattern p = Pattern.compile("\\{([012])\\}");
903 String text = getText(key);
904 Matcher m = p.matcher(text);
905 int start = 0;
906 while (m.find(start)) {
907 c.addContent(text.substring(start, m.start()));
909 Object o = null;
910 switch (m.group(1).charAt(0)) {
911 case '0': o = o0; break;
912 case '1': o = o1; break;
913 case '2': o = o2; break;
914 }
916 if (o == null) {
917 c.addContent("{" + m.group(1) + "}");
918 } else if (o instanceof String) {
919 c.addContent((String) o);
920 } else if (o instanceof Content) {
921 c.addContent((Content) o);
922 }
924 start = m.end();
925 }
927 c.addContent(text.substring(start));
928 return c;
929 }
932 /**
933 * Return true if the ClassDoc element is getting documented, depending upon
934 * -nodeprecated option and the deprecation information. Return true if
935 * -nodeprecated is not used. Return false if -nodeprecated is used and if
936 * either ClassDoc element is deprecated or the containing package is deprecated.
937 *
938 * @param cd the ClassDoc for which the page generation is checked
939 */
940 public boolean isGeneratedDoc(ClassDoc cd) {
941 if (!nodeprecated) {
942 return true;
943 }
944 return !(Util.isDeprecated(cd) || Util.isDeprecated(cd.containingPackage()));
945 }
947 /**
948 * Return the doclet specific instance of a writer factory.
949 * @return the {@link WriterFactory} for the doclet.
950 */
951 public abstract WriterFactory getWriterFactory();
953 /**
954 * Return the input stream to the builder XML.
955 *
956 * @return the input steam to the builder XML.
957 * @throws FileNotFoundException when the given XML file cannot be found.
958 */
959 public InputStream getBuilderXML() throws IOException {
960 return builderXMLPath == null ?
961 Configuration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
962 DocFile.createFileForInput(this, builderXMLPath).openInputStream();
963 }
965 /**
966 * Return the Locale for this document.
967 */
968 public abstract Locale getLocale();
970 /**
971 * Return the current file manager.
972 */
973 public abstract JavaFileManager getFileManager();
975 /**
976 * Return the comparator that will be used to sort member documentation.
977 * To no do any sorting, return null.
978 *
979 * @return the {@link java.util.Comparator} used to sort members.
980 */
981 public abstract Comparator<ProgramElementDoc> getMemberComparator();
983 private void setTabWidth(int n) {
984 sourcetab = n;
985 tabSpaces = String.format("%" + n + "s", "");
986 }
988 public abstract boolean showMessage(SourcePosition pos, String key);
989 }