001 /*
002 * Copyright 1997-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 package com.sun.tools.doclets.formats.html;
026
027 import com.sun.tools.doclets.internal.toolkit.*;
028 import com.sun.tools.doclets.internal.toolkit.builders.*;
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 * The class with "start" method, calls individual Writers.
037 *
038 * @author Atul M Dambalkar
039 * @author Robert Field
040 * @author Jamie Ho
041 *
042 */
043 public class HtmlDoclet extends AbstractDoclet {
044 public HtmlDoclet() {
045 configuration = (ConfigurationImpl) configuration();
046 }
047
048 /**
049 * The global configuration information for this run.
050 */
051 public ConfigurationImpl configuration;
052
053 /**
054 * The "start" method as required by Javadoc.
055 *
056 * @param root the root of the documentation tree.
057 * @see com.sun.javadoc.RootDoc
058 * @return true if the doclet ran without encountering any errors.
059 */
060 public static boolean start(RootDoc root) {
061 try {
062 HtmlDoclet doclet = new HtmlDoclet();
063 return doclet.start(doclet, root);
064 } finally {
065 ConfigurationImpl.reset();
066 }
067 }
068
069 /**
070 * Create the configuration instance.
071 * Override this method to use a different
072 * configuration.
073 */
074 public Configuration configuration() {
075 return ConfigurationImpl.getInstance();
076 }
077
078 /**
079 * Start the generation of files. Call generate methods in the individual
080 * writers, which will in turn genrate the documentation files. Call the
081 * TreeWriter generation first to ensure the Class Hierarchy is built
082 * first and then can be used in the later generation.
083 *
084 * For new format.
085 *
086 * @see com.sun.javadoc.RootDoc
087 */
088 protected void generateOtherFiles(RootDoc root, ClassTree classtree)
089 throws Exception {
090 super.generateOtherFiles(root, classtree);
091 if (configuration.linksource) {
092 if (configuration.destDirName.length() > 0) {
093 SourceToHTMLConverter.convertRoot(configuration,
094 root, configuration.destDirName + File.separator
095 + DocletConstants.SOURCE_OUTPUT_DIR_NAME);
096 } else {
097 SourceToHTMLConverter.convertRoot(configuration,
098 root, DocletConstants.SOURCE_OUTPUT_DIR_NAME);
099 }
100 }
101
102 if (configuration.topFile.length() == 0) {
103 configuration.standardmessage.
104 error("doclet.No_Non_Deprecated_Classes_To_Document");
105 return;
106 }
107 boolean nodeprecated = configuration.nodeprecated;
108 String configdestdir = configuration.destDirName;
109 String confighelpfile = configuration.helpfile;
110 String configstylefile = configuration.stylesheetfile;
111 performCopy(configdestdir, confighelpfile);
112 performCopy(configdestdir, configstylefile);
113 Util.copyResourceFile(configuration, "inherit.gif", false);
114 // do early to reduce memory footprint
115 if (configuration.classuse) {
116 ClassUseWriter.generate(configuration, classtree);
117 }
118 IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated);
119
120 if (configuration.createtree) {
121 TreeWriter.generate(configuration, classtree);
122 }
123 if (configuration.createindex) {
124 if (configuration.splitindex) {
125 SplitIndexWriter.generate(configuration, indexbuilder);
126 } else {
127 SingleIndexWriter.generate(configuration, indexbuilder);
128 }
129 }
130
131 if (!(configuration.nodeprecatedlist || nodeprecated)) {
132 DeprecatedListWriter.generate(configuration);
133 }
134
135 AllClassesFrameWriter.generate(configuration,
136 new IndexBuilder(configuration, nodeprecated, true));
137
138 FrameOutputWriter.generate(configuration);
139
140 if (configuration.createoverview) {
141 PackageIndexWriter.generate(configuration);
142 }
143 if (configuration.helpfile.length() == 0 &&
144 !configuration.nohelp) {
145 HelpWriter.generate(configuration);
146 }
147 if (configuration.stylesheetfile.length() == 0) {
148 StylesheetWriter.generate(configuration);
149 }
150 }
151
152 /**
153 * {@inheritDoc}
154 */
155 protected void generateClassFiles(ClassDoc[] arr, ClassTree classtree) {
156 Arrays.sort(arr);
157 for(int i = 0; i < arr.length; i++) {
158 if (!(configuration.isGeneratedDoc(arr[i]) && arr[i].isIncluded())) {
159 continue;
160 }
161 ClassDoc prev = (i == 0)?
162 null:
163 arr[i-1];
164 ClassDoc curr = arr[i];
165 ClassDoc next = (i+1 == arr.length)?
166 null:
167 arr[i+1];
168 try {
169 if (curr.isAnnotationType()) {
170 AbstractBuilder annotationTypeBuilder =
171 configuration.getBuilderFactory()
172 .getAnnotationTypeBuilder((AnnotationTypeDoc) curr,
173 prev, next);
174 annotationTypeBuilder.build();
175 } else {
176 AbstractBuilder classBuilder =
177 configuration.getBuilderFactory()
178 .getClassBuilder(curr, prev, next, classtree);
179 classBuilder.build();
180 }
181 } catch (Exception e) {
182 e.printStackTrace();
183 throw new DocletAbortException();
184 }
185 }
186 }
187
188 /**
189 * {@inheritDoc}
190 */
191 protected void generatePackageFiles(ClassTree classtree) throws Exception {
192 PackageDoc[] packages = configuration.packages;
193 if (packages.length > 1) {
194 PackageIndexFrameWriter.generate(configuration);
195 }
196 PackageDoc prev = null, next;
197 for(int i = 0; i < packages.length; i++) {
198 PackageFrameWriter.generate(configuration, packages[i]);
199 next = (i + 1 < packages.length && packages[i+1].name().length() > 0) ?
200 packages[i+1] : null;
201 //If the next package is unnamed package, skip 2 ahead if possible
202 next = (i + 2 < packages.length && next == null) ?
203 packages[i+2]: next;
204 AbstractBuilder packageSummaryBuilder = configuration.
205 getBuilderFactory().getPackageSummaryBuilder(
206 packages[i], prev, next);
207 packageSummaryBuilder.build();
208 if (configuration.createtree) {
209 PackageTreeWriter.generate(configuration,
210 packages[i], prev, next,
211 configuration.nodeprecated);
212 }
213 prev = packages[i];
214 }
215 }
216
217 /**
218 * Check for doclet added options here.
219 *
220 * @return number of arguments to option. Zero return means
221 * option not known. Negative value means error occurred.
222 */
223 public static int optionLength(String option) {
224 // Construct temporary configuration for check
225 return (ConfigurationImpl.getInstance()).optionLength(option);
226 }
227
228 /**
229 * Check that options have the correct arguments here.
230 * <P>
231 * This method is not required and will default gracefully
232 * (to true) if absent.
233 * <P>
234 * Printing option related error messages (using the provided
235 * DocErrorReporter) is the responsibility of this method.
236 *
237 * @return true if the options are valid.
238 */
239 public static boolean validOptions(String options[][],
240 DocErrorReporter reporter) {
241 // Construct temporary configuration for check
242 return (ConfigurationImpl.getInstance()).validOptions(options, reporter);
243 }
244
245 private void performCopy(String configdestdir, String filename) {
246 try {
247 String destdir = (configdestdir.length() > 0) ?
248 configdestdir + File.separatorChar: "";
249 if (filename.length() > 0) {
250 File helpstylefile = new File(filename);
251 String parent = helpstylefile.getParent();
252 String helpstylefilename = (parent == null)?
253 filename:
254 filename.substring(parent.length() + 1);
255 File desthelpfile = new File(destdir + helpstylefilename);
256 if (!desthelpfile.getCanonicalPath().equals(
257 helpstylefile.getCanonicalPath())) {
258 configuration.message.
259 notice((SourcePosition) null,
260 "doclet.Copying_File_0_To_File_1",
261 helpstylefile.toString(), desthelpfile.toString());
262 Util.copyFile(desthelpfile, helpstylefile);
263 }
264 }
265 } catch (IOException exc) {
266 configuration.message.
267 error((SourcePosition) null,
268 "doclet.perform_copy_exception_encountered",
269 exc.toString());
270 throw new DocletAbortException();
271 }
272 }
273 }