duke@1: /* ohair@554: * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: package com.sun.tools.doclets.formats.html; duke@1: duke@1: import com.sun.tools.doclets.internal.toolkit.*; duke@1: import com.sun.tools.doclets.internal.toolkit.builders.*; duke@1: import com.sun.tools.doclets.internal.toolkit.util.*; duke@1: duke@1: import com.sun.javadoc.*; duke@1: import java.util.*; duke@1: import java.io.*; duke@1: duke@1: /** duke@1: * The class with "start" method, calls individual Writers. duke@1: * duke@1: * @author Atul M Dambalkar duke@1: * @author Robert Field duke@1: * @author Jamie Ho duke@1: * duke@1: */ duke@1: public class HtmlDoclet extends AbstractDoclet { jjg@140: public HtmlDoclet() { jjg@140: configuration = (ConfigurationImpl) configuration(); jjg@140: } duke@1: duke@1: /** duke@1: * The global configuration information for this run. duke@1: */ jjg@140: public ConfigurationImpl configuration; duke@1: duke@1: /** duke@1: * The "start" method as required by Javadoc. duke@1: * duke@1: * @param root the root of the documentation tree. duke@1: * @see com.sun.javadoc.RootDoc duke@1: * @return true if the doclet ran without encountering any errors. duke@1: */ duke@1: public static boolean start(RootDoc root) { jjg@140: try { jjg@140: HtmlDoclet doclet = new HtmlDoclet(); jjg@140: return doclet.start(doclet, root); jjg@140: } finally { jjg@140: ConfigurationImpl.reset(); jjg@140: } duke@1: } duke@1: duke@1: /** duke@1: * Create the configuration instance. duke@1: * Override this method to use a different duke@1: * configuration. duke@1: */ duke@1: public Configuration configuration() { duke@1: return ConfigurationImpl.getInstance(); duke@1: } duke@1: duke@1: /** duke@1: * Start the generation of files. Call generate methods in the individual duke@1: * writers, which will in turn genrate the documentation files. Call the duke@1: * TreeWriter generation first to ensure the Class Hierarchy is built duke@1: * first and then can be used in the later generation. duke@1: * duke@1: * For new format. duke@1: * duke@1: * @see com.sun.javadoc.RootDoc duke@1: */ duke@1: protected void generateOtherFiles(RootDoc root, ClassTree classtree) duke@1: throws Exception { duke@1: super.generateOtherFiles(root, classtree); duke@1: if (configuration.linksource) { duke@1: if (configuration.destDirName.length() > 0) { duke@1: SourceToHTMLConverter.convertRoot(configuration, duke@1: root, configuration.destDirName + File.separator duke@1: + DocletConstants.SOURCE_OUTPUT_DIR_NAME); duke@1: } else { duke@1: SourceToHTMLConverter.convertRoot(configuration, duke@1: root, DocletConstants.SOURCE_OUTPUT_DIR_NAME); duke@1: } duke@1: } duke@1: duke@1: if (configuration.topFile.length() == 0) { duke@1: configuration.standardmessage. duke@1: error("doclet.No_Non_Deprecated_Classes_To_Document"); duke@1: return; duke@1: } duke@1: boolean nodeprecated = configuration.nodeprecated; duke@1: String configdestdir = configuration.destDirName; duke@1: String confighelpfile = configuration.helpfile; duke@1: String configstylefile = configuration.stylesheetfile; duke@1: performCopy(configdestdir, confighelpfile); duke@1: performCopy(configdestdir, configstylefile); duke@1: Util.copyResourceFile(configuration, "inherit.gif", false); duke@1: // do early to reduce memory footprint duke@1: if (configuration.classuse) { duke@1: ClassUseWriter.generate(configuration, classtree); duke@1: } duke@1: IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated); duke@1: duke@1: if (configuration.createtree) { duke@1: TreeWriter.generate(configuration, classtree); duke@1: } duke@1: if (configuration.createindex) { duke@1: if (configuration.splitindex) { duke@1: SplitIndexWriter.generate(configuration, indexbuilder); duke@1: } else { duke@1: SingleIndexWriter.generate(configuration, indexbuilder); duke@1: } duke@1: } duke@1: duke@1: if (!(configuration.nodeprecatedlist || nodeprecated)) { duke@1: DeprecatedListWriter.generate(configuration); duke@1: } duke@1: duke@1: AllClassesFrameWriter.generate(configuration, duke@1: new IndexBuilder(configuration, nodeprecated, true)); duke@1: duke@1: FrameOutputWriter.generate(configuration); duke@1: duke@1: if (configuration.createoverview) { duke@1: PackageIndexWriter.generate(configuration); duke@1: } duke@1: if (configuration.helpfile.length() == 0 && duke@1: !configuration.nohelp) { duke@1: HelpWriter.generate(configuration); duke@1: } bpatel@766: // If a stylesheet file is not specified, copy the default stylesheet. duke@1: if (configuration.stylesheetfile.length() == 0) { bpatel@766: Util.copyFile(configuration, "stylesheet.css", Util.RESOURCESDIR, bpatel@766: (configdestdir.isEmpty()) ? bpatel@766: System.getProperty("user.dir") : configdestdir, false); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: protected void generateClassFiles(ClassDoc[] arr, ClassTree classtree) { duke@1: Arrays.sort(arr); duke@1: for(int i = 0; i < arr.length; i++) { duke@1: if (!(configuration.isGeneratedDoc(arr[i]) && arr[i].isIncluded())) { duke@1: continue; duke@1: } duke@1: ClassDoc prev = (i == 0)? duke@1: null: duke@1: arr[i-1]; duke@1: ClassDoc curr = arr[i]; duke@1: ClassDoc next = (i+1 == arr.length)? duke@1: null: duke@1: arr[i+1]; duke@1: try { duke@1: if (curr.isAnnotationType()) { duke@1: AbstractBuilder annotationTypeBuilder = duke@1: configuration.getBuilderFactory() duke@1: .getAnnotationTypeBuilder((AnnotationTypeDoc) curr, duke@1: prev, next); duke@1: annotationTypeBuilder.build(); duke@1: } else { duke@1: AbstractBuilder classBuilder = duke@1: configuration.getBuilderFactory() duke@1: .getClassBuilder(curr, prev, next, classtree); duke@1: classBuilder.build(); duke@1: } duke@1: } catch (Exception e) { duke@1: e.printStackTrace(); duke@1: throw new DocletAbortException(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: protected void generatePackageFiles(ClassTree classtree) throws Exception { duke@1: PackageDoc[] packages = configuration.packages; duke@1: if (packages.length > 1) { duke@1: PackageIndexFrameWriter.generate(configuration); duke@1: } duke@1: PackageDoc prev = null, next; duke@1: for(int i = 0; i < packages.length; i++) { duke@1: PackageFrameWriter.generate(configuration, packages[i]); duke@1: next = (i + 1 < packages.length && packages[i+1].name().length() > 0) ? duke@1: packages[i+1] : null; duke@1: //If the next package is unnamed package, skip 2 ahead if possible duke@1: next = (i + 2 < packages.length && next == null) ? duke@1: packages[i+2]: next; duke@1: AbstractBuilder packageSummaryBuilder = configuration. duke@1: getBuilderFactory().getPackageSummaryBuilder( duke@1: packages[i], prev, next); duke@1: packageSummaryBuilder.build(); duke@1: if (configuration.createtree) { duke@1: PackageTreeWriter.generate(configuration, duke@1: packages[i], prev, next, duke@1: configuration.nodeprecated); duke@1: } duke@1: prev = packages[i]; duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Check for doclet added options here. duke@1: * duke@1: * @return number of arguments to option. Zero return means duke@1: * option not known. Negative value means error occurred. duke@1: */ duke@1: public static int optionLength(String option) { duke@1: // Construct temporary configuration for check duke@1: return (ConfigurationImpl.getInstance()).optionLength(option); duke@1: } duke@1: duke@1: /** duke@1: * Check that options have the correct arguments here. duke@1: *

duke@1: * This method is not required and will default gracefully duke@1: * (to true) if absent. duke@1: *

duke@1: * Printing option related error messages (using the provided duke@1: * DocErrorReporter) is the responsibility of this method. duke@1: * duke@1: * @return true if the options are valid. duke@1: */ duke@1: public static boolean validOptions(String options[][], duke@1: DocErrorReporter reporter) { duke@1: // Construct temporary configuration for check duke@1: return (ConfigurationImpl.getInstance()).validOptions(options, reporter); duke@1: } duke@1: duke@1: private void performCopy(String configdestdir, String filename) { duke@1: try { duke@1: String destdir = (configdestdir.length() > 0) ? duke@1: configdestdir + File.separatorChar: ""; duke@1: if (filename.length() > 0) { duke@1: File helpstylefile = new File(filename); duke@1: String parent = helpstylefile.getParent(); duke@1: String helpstylefilename = (parent == null)? duke@1: filename: duke@1: filename.substring(parent.length() + 1); duke@1: File desthelpfile = new File(destdir + helpstylefilename); duke@1: if (!desthelpfile.getCanonicalPath().equals( duke@1: helpstylefile.getCanonicalPath())) { duke@1: configuration.message. duke@1: notice((SourcePosition) null, duke@1: "doclet.Copying_File_0_To_File_1", duke@1: helpstylefile.toString(), desthelpfile.toString()); duke@1: Util.copyFile(desthelpfile, helpstylefile); duke@1: } duke@1: } duke@1: } catch (IOException exc) { duke@1: configuration.message. duke@1: error((SourcePosition) null, duke@1: "doclet.perform_copy_exception_encountered", duke@1: exc.toString()); duke@1: throw new DocletAbortException(); duke@1: } duke@1: } duke@1: }