001    /*
002     * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.doclets.formats.html;
027    
028    import com.sun.tools.doclets.internal.toolkit.*;
029    import com.sun.tools.doclets.internal.toolkit.util.*;
030    
031    import com.sun.javadoc.*;
032    import java.util.*;
033    import java.io.*;
034    
035    /**
036     * Configure the output based on the command line options.
037     * <p>
038     * Also determine the length of the command line option. For example,
039     * for a option "-header" there will be a string argument associated, then the
040     * the length of option "-header" is two. But for option "-nohelp" no argument
041     * is needed so it's length is 1.
042     * </p>
043     * <p>
044     * Also do the error checking on the options used. For example it is illegal to
045     * use "-helpfile" option when already "-nohelp" option is used.
046     * </p>
047     *
048     * @author Robert Field.
049     * @author Atul Dambalkar.
050     * @author Jamie Ho
051     */
052    public class ConfigurationImpl extends Configuration {
053    
054        private static ConfigurationImpl instance = new ConfigurationImpl();
055    
056        /**
057         * The build date.  Note: For now, we will use
058         * a version number instead of a date.
059         */
060        public static final String BUILD_DATE = System.getProperty("java.version");
061    
062        /**
063         * The name of the constant values file.
064         */
065        public static final String CONSTANTS_FILE_NAME = "constant-values.html";
066    
067        /**
068         * Argument for command line option "-header".
069         */
070        public String header = "";
071    
072        /**
073         * Argument for command line option "-packagesheader".
074         */
075        public String packagesheader = "";
076    
077        /**
078         * Argument for command line option "-footer".
079         */
080        public String footer = "";
081    
082        /**
083         * Argument for command line option "-doctitle".
084         */
085        public String doctitle = "";
086    
087        /**
088         * Argument for command line option "-windowtitle".
089         */
090        public String windowtitle = "";
091    
092        /**
093         * Argument for command line option "-top".
094         */
095        public String top = "";
096    
097        /**
098         * Argument for command line option "-bottom".
099         */
100        public String bottom = "";
101    
102        /**
103         * Argument for command line option "-helpfile".
104         */
105        public String helpfile = "";
106    
107        /**
108         * Argument for command line option "-stylesheetfile".
109         */
110        public String stylesheetfile = "";
111    
112        /**
113         * True if command line option "-nohelp" is used. Default value is false.
114         */
115        public boolean nohelp = false;
116    
117        /**
118         * True if command line option "-splitindex" is used. Default value is
119         * false.
120         */
121        public boolean splitindex = false;
122    
123        /**
124         * False if command line option "-noindex" is used. Default value is true.
125         */
126        public boolean createindex = true;
127    
128        /**
129         * True if command line option "-use" is used. Default value is false.
130         */
131        public boolean classuse = false;
132    
133        /**
134         * False if command line option "-notree" is used. Default value is true.
135         */
136        public boolean createtree = true;
137    
138        /**
139         * True if command line option "-nodeprecated" is used. Default value is
140         * false.
141         */
142        public boolean nodeprecatedlist = false;
143    
144        /**
145         * True if command line option "-nonavbar" is used. Default value is false.
146         */
147        public boolean nonavbar = false;
148    
149        /**
150         * True if command line option "-nooverview" is used. Default value is
151         * false
152         */
153        private boolean nooverview = false;
154    
155        /**
156         * True if command line option "-overview" is used. Default value is false.
157         */
158        public boolean overview = false;
159    
160        /**
161         * This is true if option "-overview" is used or option "-overview" is not
162         * used and number of packages is more than one.
163         */
164        public boolean createoverview = false;
165    
166        /**
167         * Unique Resource Handler for this package.
168         */
169        public final MessageRetriever standardmessage;
170    
171        /**
172         * First file to appear in the right-hand frame in the generated
173         * documentation.
174         */
175        public String topFile = "";
176    
177        /**
178         * The classdoc for the class file getting generated.
179         */
180        public ClassDoc currentcd = null;  // Set this classdoc in the
181        // ClassWriter.
182    
183        /**
184         * Constructor. Initialises resource for the
185         * {@link com.sun.tools.doclets.MessageRetriever}.
186         */
187        private ConfigurationImpl() {
188            standardmessage = new MessageRetriever(this,
189                "com.sun.tools.doclets.formats.html.resources.standard");
190        }
191    
192        /**
193         * Reset to a fresh new ConfigurationImpl, to allow multiple invocations
194         * of javadoc within a single VM. It would be better not to be using
195         * static fields at all, but .... (sigh).
196         */
197        public static void reset() {
198            instance = new ConfigurationImpl();
199        }
200    
201        public static ConfigurationImpl getInstance() {
202            return instance;
203        }
204    
205        /**
206         * Return the build date for the doclet.
207         */
208        public String getDocletSpecificBuildDate() {
209            return BUILD_DATE;
210        }
211    
212        /**
213         * Depending upon the command line options provided by the user, set
214         * configure the output generation environment.
215         *
216         * @param options The array of option names and values.
217         */
218        public void setSpecificDocletOptions(String[][] options) {
219            for (int oi = 0; oi < options.length; ++oi) {
220                String[] os = options[oi];
221                String opt = os[0].toLowerCase();
222                if (opt.equals("-footer")) {
223                    footer =  os[1];
224                } else  if (opt.equals("-header")) {
225                    header =  os[1];
226                } else  if (opt.equals("-packagesheader")) {
227                    packagesheader =  os[1];
228                } else  if (opt.equals("-doctitle")) {
229                    doctitle =  os[1];
230                } else  if (opt.equals("-windowtitle")) {
231                    windowtitle =  os[1];
232                } else  if (opt.equals("-top")) {
233                    top =  os[1];
234                } else  if (opt.equals("-bottom")) {
235                    bottom =  os[1];
236                } else  if (opt.equals("-helpfile")) {
237                    helpfile =  os[1];
238                } else  if (opt.equals("-stylesheetfile")) {
239                    stylesheetfile =  os[1];
240                } else  if (opt.equals("-charset")) {
241                    charset =  os[1];
242                } else  if (opt.equals("-nohelp")) {
243                    nohelp = true;
244                } else  if (opt.equals("-splitindex")) {
245                    splitindex = true;
246                } else  if (opt.equals("-noindex")) {
247                    createindex = false;
248                } else  if (opt.equals("-use")) {
249                    classuse = true;
250                } else  if (opt.equals("-notree")) {
251                    createtree = false;
252                } else  if (opt.equals("-nodeprecatedlist")) {
253                    nodeprecatedlist = true;
254                } else  if (opt.equals("-nosince")) {
255                    nosince = true;
256                } else  if (opt.equals("-nonavbar")) {
257                    nonavbar = true;
258                } else  if (opt.equals("-nooverview")) {
259                    nooverview = true;
260                } else  if (opt.equals("-overview")) {
261                    overview = true;
262                }
263            }
264            if (root.specifiedClasses().length > 0) {
265                Map<String,PackageDoc> map = new HashMap<String,PackageDoc>();
266                PackageDoc pd;
267                ClassDoc[] classes = root.classes();
268                for (int i = 0; i < classes.length; i++) {
269                    pd = classes[i].containingPackage();
270                    if(! map.containsKey(pd.name())) {
271                        map.put(pd.name(), pd);
272                    }
273                }
274            }
275            setCreateOverview();
276            setTopFile(root);
277        }
278    
279        /**
280         * Returns the "length" of a given option. If an option takes no
281         * arguments, its length is one. If it takes one argument, it's
282         * length is two, and so on. This method is called by JavaDoc to
283         * parse the options it does not recognize. It then calls
284         * {@link #validOptions(String[][], DocErrorReporter)} to
285         * validate them.
286         * <b>Note:</b><br>
287         * The options arrive as case-sensitive strings. For options that
288         * are not case-sensitive, use toLowerCase() on the option string
289         * before comparing it.
290         * </blockquote>
291         *
292         * @return number of arguments + 1 for a option. Zero return means
293         * option not known.  Negative value means error occurred.
294         */
295        public int optionLength(String option) {
296            int result = -1;
297            if ((result = super.optionLength(option)) > 0) {
298                return result;
299            }
300            // otherwise look for the options we have added
301            option = option.toLowerCase();
302            if (option.equals("-nodeprecatedlist") ||
303                option.equals("-noindex") ||
304                option.equals("-notree") ||
305                option.equals("-nohelp") ||
306                option.equals("-splitindex") ||
307                option.equals("-serialwarn") ||
308                option.equals("-use") ||
309                option.equals("-nonavbar") ||
310                option.equals("-nooverview")) {
311                return 1;
312            } else if (option.equals("-help")) {
313                System.out.println(getText("doclet.usage"));
314                return 1;
315            } else if (option.equals("-footer") ||
316                       option.equals("-header") ||
317                       option.equals("-packagesheader") ||
318                       option.equals("-doctitle") ||
319                       option.equals("-windowtitle") ||
320                       option.equals("-top") ||
321                       option.equals("-bottom") ||
322                       option.equals("-helpfile") ||
323                       option.equals("-stylesheetfile") ||
324                       option.equals("-charset") ||
325                       option.equals("-overview")) {
326                return 2;
327            } else {
328                return 0;
329            }
330        }
331    
332        /**
333         * {@inheritDoc}
334         */
335        public boolean validOptions(String options[][],
336                DocErrorReporter reporter) {
337            boolean helpfile = false;
338            boolean nohelp = false;
339            boolean overview = false;
340            boolean nooverview = false;
341            boolean splitindex = false;
342            boolean noindex = false;
343            // check shared options
344            if (!generalValidOptions(options, reporter)) {
345                return false;
346            }
347            // otherwise look at our options
348            for (int oi = 0; oi < options.length; ++oi) {
349                String[] os = options[oi];
350                String opt = os[0].toLowerCase();
351                if (opt.equals("-helpfile")) {
352                    if (nohelp == true) {
353                        reporter.printError(getText("doclet.Option_conflict",
354                            "-helpfile", "-nohelp"));
355                        return false;
356                    }
357                    if (helpfile == true) {
358                        reporter.printError(getText("doclet.Option_reuse",
359                            "-helpfile"));
360                        return false;
361                    }
362                    File help = new File(os[1]);
363                    if (!help.exists()) {
364                        reporter.printError(getText("doclet.File_not_found", os[1]));
365                        return false;
366                    }
367                    helpfile = true;
368                } else  if (opt.equals("-nohelp")) {
369                    if (helpfile == true) {
370                        reporter.printError(getText("doclet.Option_conflict",
371                            "-nohelp", "-helpfile"));
372                        return false;
373                    }
374                    nohelp = true;
375                } else if (opt.equals("-overview")) {
376                    if (nooverview == true) {
377                        reporter.printError(getText("doclet.Option_conflict",
378                            "-overview", "-nooverview"));
379                        return false;
380                    }
381                    if (overview == true) {
382                        reporter.printError(getText("doclet.Option_reuse",
383                            "-overview"));
384                        return false;
385                    }
386                    overview = true;
387                } else  if (opt.equals("-nooverview")) {
388                    if (overview == true) {
389                        reporter.printError(getText("doclet.Option_conflict",
390                            "-nooverview", "-overview"));
391                        return false;
392                    }
393                    nooverview = true;
394                } else if (opt.equals("-splitindex")) {
395                    if (noindex == true) {
396                        reporter.printError(getText("doclet.Option_conflict",
397                            "-splitindex", "-noindex"));
398                        return false;
399                    }
400                    splitindex = true;
401                } else if (opt.equals("-noindex")) {
402                    if (splitindex == true) {
403                        reporter.printError(getText("doclet.Option_conflict",
404                            "-noindex", "-splitindex"));
405                        return false;
406                    }
407                    noindex = true;
408                }
409            }
410            return true;
411        }
412    
413        /**
414         * {@inheritDoc}
415         */
416        public MessageRetriever getDocletSpecificMsg() {
417            return standardmessage;
418        }
419    
420        /**
421         * Decide the page which will appear first in the right-hand frame. It will
422         * be "overview-summary.html" if "-overview" option is used or no
423         * "-overview" but the number of packages is more than one. It will be
424         * "package-summary.html" of the respective package if there is only one
425         * package to document. It will be a class page(first in the sorted order),
426         * if only classes are provided on the command line.
427         *
428         * @param root Root of the program structure.
429         */
430        protected void setTopFile(RootDoc root) {
431            if (!checkForDeprecation(root)) {
432                return;
433            }
434            if (createoverview) {
435                topFile = "overview-summary.html";
436            } else {
437                if (packages.length == 1 && packages[0].name().equals("")) {
438                    if (root.classes().length > 0) {
439                        ClassDoc[] classarr = root.classes();
440                        Arrays.sort(classarr);
441                        ClassDoc cd = getValidClass(classarr);
442                        topFile = DirectoryManager.getPathToClass(cd);
443                    }
444                } else {
445                    topFile = DirectoryManager.getPathToPackage(packages[0],
446                                                                "package-summary.html");
447                }
448            }
449        }
450    
451        protected ClassDoc getValidClass(ClassDoc[] classarr) {
452            if (!nodeprecated) {
453                return classarr[0];
454            }
455            for (int i = 0; i < classarr.length; i++) {
456                if (classarr[i].tags("deprecated").length == 0) {
457                    return classarr[i];
458                }
459            }
460            return null;
461        }
462    
463        protected boolean checkForDeprecation(RootDoc root) {
464            ClassDoc[] classarr = root.classes();
465            for (int i = 0; i < classarr.length; i++) {
466                if (isGeneratedDoc(classarr[i])) {
467                    return true;
468                }
469            }
470            return false;
471        }
472    
473        /**
474         * Generate "overview.html" page if option "-overview" is used or number of
475         * packages is more than one. Sets {@link #createoverview} field to true.
476         */
477        protected void setCreateOverview() {
478            if ((overview || packages.length > 1) && !nooverview) {
479                createoverview = true;
480            }
481        }
482    
483        /**
484         * {@inheritDoc}
485         */
486        public WriterFactory getWriterFactory() {
487            return new WriterFactoryImpl(this);
488        }
489    
490        /**
491         * {@inheritDoc}
492         */
493        public Comparator<ProgramElementDoc> getMemberComparator() {
494            return null;
495        }
496    
497        /**
498         * {@inheritDoc}
499         */
500        public Locale getLocale() {
501            if (root instanceof com.sun.tools.javadoc.RootDocImpl)
502                return ((com.sun.tools.javadoc.RootDocImpl)root).getLocale();
503            else
504                return Locale.getDefault();
505        }
506    }