Fri, 05 Oct 2012 14:16:32 -0700
7068595: html files in class-use dir do not get loaded correctly when Frames link is clicked
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1997, 2011, 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 package com.sun.tools.doclets.formats.html;
27 import com.sun.tools.doclets.internal.toolkit.*;
28 import com.sun.tools.doclets.internal.toolkit.builders.*;
29 import com.sun.tools.doclets.internal.toolkit.util.*;
31 import com.sun.javadoc.*;
32 import java.util.*;
33 import java.io.*;
35 /**
36 * The class with "start" method, calls individual Writers.
37 *
38 * @author Atul M Dambalkar
39 * @author Robert Field
40 * @author Jamie Ho
41 *
42 */
43 public class HtmlDoclet extends AbstractDoclet {
44 public HtmlDoclet() {
45 configuration = (ConfigurationImpl) configuration();
46 }
48 /**
49 * The global configuration information for this run.
50 */
51 public ConfigurationImpl configuration;
53 /**
54 * The "start" method as required by Javadoc.
55 *
56 * @param root the root of the documentation tree.
57 * @see com.sun.javadoc.RootDoc
58 * @return true if the doclet ran without encountering any errors.
59 */
60 public static boolean start(RootDoc root) {
61 try {
62 HtmlDoclet doclet = new HtmlDoclet();
63 return doclet.start(doclet, root);
64 } finally {
65 ConfigurationImpl.reset();
66 }
67 }
69 /**
70 * Create the configuration instance.
71 * Override this method to use a different
72 * configuration.
73 */
74 public Configuration configuration() {
75 return ConfigurationImpl.getInstance();
76 }
78 /**
79 * Start the generation of files. Call generate methods in the individual
80 * writers, which will in turn genrate the documentation files. Call the
81 * TreeWriter generation first to ensure the Class Hierarchy is built
82 * first and then can be used in the later generation.
83 *
84 * For new format.
85 *
86 * @see com.sun.javadoc.RootDoc
87 */
88 protected void generateOtherFiles(RootDoc root, ClassTree classtree)
89 throws Exception {
90 super.generateOtherFiles(root, classtree);
91 if (configuration.linksource) {
92 if (configuration.destDirName.length() > 0) {
93 SourceToHTMLConverter.convertRoot(configuration,
94 root, configuration.destDirName + File.separator
95 + DocletConstants.SOURCE_OUTPUT_DIR_NAME);
96 } else {
97 SourceToHTMLConverter.convertRoot(configuration,
98 root, DocletConstants.SOURCE_OUTPUT_DIR_NAME);
99 }
100 }
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, "background.gif", false);
114 Util.copyResourceFile(configuration, "tab.gif", false);
115 Util.copyResourceFile(configuration, "titlebar.gif", false);
116 Util.copyResourceFile(configuration, "titlebar_end.gif", false);
117 // do early to reduce memory footprint
118 if (configuration.classuse) {
119 ClassUseWriter.generate(configuration, classtree);
120 }
121 IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated);
123 if (configuration.createtree) {
124 TreeWriter.generate(configuration, classtree);
125 }
126 if (configuration.createindex) {
127 if (configuration.splitindex) {
128 SplitIndexWriter.generate(configuration, indexbuilder);
129 } else {
130 SingleIndexWriter.generate(configuration, indexbuilder);
131 }
132 }
134 if (!(configuration.nodeprecatedlist || nodeprecated)) {
135 DeprecatedListWriter.generate(configuration);
136 }
138 AllClassesFrameWriter.generate(configuration,
139 new IndexBuilder(configuration, nodeprecated, true));
141 FrameOutputWriter.generate(configuration);
143 if (configuration.createoverview) {
144 PackageIndexWriter.generate(configuration);
145 }
146 if (configuration.helpfile.length() == 0 &&
147 !configuration.nohelp) {
148 HelpWriter.generate(configuration);
149 }
150 // If a stylesheet file is not specified, copy the default stylesheet
151 // and replace newline with platform-specific newline.
152 if (configuration.stylesheetfile.length() == 0) {
153 Util.copyFile(configuration, "stylesheet.css", Util.RESOURCESDIR,
154 (configdestdir.isEmpty()) ?
155 System.getProperty("user.dir") : configdestdir, false, true);
156 }
157 }
159 /**
160 * {@inheritDoc}
161 */
162 protected void generateClassFiles(ClassDoc[] arr, ClassTree classtree) {
163 Arrays.sort(arr);
164 for(int i = 0; i < arr.length; i++) {
165 if (!(configuration.isGeneratedDoc(arr[i]) && arr[i].isIncluded())) {
166 continue;
167 }
168 ClassDoc prev = (i == 0)?
169 null:
170 arr[i-1];
171 ClassDoc curr = arr[i];
172 ClassDoc next = (i+1 == arr.length)?
173 null:
174 arr[i+1];
175 try {
176 if (curr.isAnnotationType()) {
177 AbstractBuilder annotationTypeBuilder =
178 configuration.getBuilderFactory()
179 .getAnnotationTypeBuilder((AnnotationTypeDoc) curr,
180 prev, next);
181 annotationTypeBuilder.build();
182 } else {
183 AbstractBuilder classBuilder =
184 configuration.getBuilderFactory()
185 .getClassBuilder(curr, prev, next, classtree);
186 classBuilder.build();
187 }
188 } catch (Exception e) {
189 e.printStackTrace();
190 throw new DocletAbortException();
191 }
192 }
193 }
195 /**
196 * {@inheritDoc}
197 */
198 protected void generatePackageFiles(ClassTree classtree) throws Exception {
199 PackageDoc[] packages = configuration.packages;
200 if (packages.length > 1) {
201 PackageIndexFrameWriter.generate(configuration);
202 }
203 PackageDoc prev = null, next;
204 for (int i = 0; i < packages.length; i++) {
205 // if -nodeprecated option is set and the package is marked as
206 // deprecated, do not generate the package-summary.html, package-frame.html
207 // and package-tree.html pages for that package.
208 if (!(configuration.nodeprecated && Util.isDeprecated(packages[i]))) {
209 PackageFrameWriter.generate(configuration, packages[i]);
210 next = (i + 1 < packages.length &&
211 packages[i + 1].name().length() > 0) ? packages[i + 1] : null;
212 //If the next package is unnamed package, skip 2 ahead if possible
213 next = (i + 2 < packages.length && next == null) ? packages[i + 2] : next;
214 AbstractBuilder packageSummaryBuilder =
215 configuration.getBuilderFactory().getPackageSummaryBuilder(
216 packages[i], prev, next);
217 packageSummaryBuilder.build();
218 if (configuration.createtree) {
219 PackageTreeWriter.generate(configuration,
220 packages[i], prev, next,
221 configuration.nodeprecated);
222 }
223 prev = packages[i];
224 }
225 }
226 }
228 /**
229 * Check for doclet added options here.
230 *
231 * @return number of arguments to option. Zero return means
232 * option not known. Negative value means error occurred.
233 */
234 public static int optionLength(String option) {
235 // Construct temporary configuration for check
236 return (ConfigurationImpl.getInstance()).optionLength(option);
237 }
239 /**
240 * Check that options have the correct arguments here.
241 * <P>
242 * This method is not required and will default gracefully
243 * (to true) if absent.
244 * <P>
245 * Printing option related error messages (using the provided
246 * DocErrorReporter) is the responsibility of this method.
247 *
248 * @return true if the options are valid.
249 */
250 public static boolean validOptions(String options[][],
251 DocErrorReporter reporter) {
252 // Construct temporary configuration for check
253 return (ConfigurationImpl.getInstance()).validOptions(options, reporter);
254 }
256 private void performCopy(String configdestdir, String filename) {
257 try {
258 String destdir = (configdestdir.length() > 0) ?
259 configdestdir + File.separatorChar: "";
260 if (filename.length() > 0) {
261 File helpstylefile = new File(filename);
262 String parent = helpstylefile.getParent();
263 String helpstylefilename = (parent == null)?
264 filename:
265 filename.substring(parent.length() + 1);
266 File desthelpfile = new File(destdir + helpstylefilename);
267 if (!desthelpfile.getCanonicalPath().equals(
268 helpstylefile.getCanonicalPath())) {
269 configuration.message.
270 notice((SourcePosition) null,
271 "doclet.Copying_File_0_To_File_1",
272 helpstylefile.toString(), desthelpfile.toString());
273 Util.copyFile(desthelpfile, helpstylefile);
274 }
275 }
276 } catch (IOException exc) {
277 configuration.message.
278 error((SourcePosition) null,
279 "doclet.perform_copy_exception_encountered",
280 exc.toString());
281 throw new DocletAbortException();
282 }
283 }
284 }