1 /* 2 * Copyright (c) 1997, 2015, 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 26 package com.sun.tools.doclets.formats.html.markup; 27 28 import java.io.*; 29 import java.util.*; 30 31 import com.sun.javadoc.*; 32 import com.sun.tools.doclets.formats.html.ConfigurationImpl; 33 import com.sun.tools.doclets.formats.html.SectionName; 34 import com.sun.tools.doclets.internal.toolkit.*; 35 import com.sun.tools.doclets.internal.toolkit.util.DocFile; 36 import com.sun.tools.doclets.internal.toolkit.util.DocLink; 37 import com.sun.tools.doclets.internal.toolkit.util.DocPath; 38 import com.sun.tools.doclets.internal.toolkit.util.DocPaths; 39 40 41 /** 42 * Class for the Html Format Code Generation specific to JavaDoc. 43 * This Class contains methods related to the Html Code Generation which 44 * are used by the Sub-Classes in the package com.sun.tools.doclets.standard 45 * and com.sun.tools.doclets.oneone. 46 * 47 * <p><b>This is NOT part of any supported API. 48 * If you write code that depends on this, you do so at your own risk. 49 * This code and its internal interfaces are subject to change or 50 * deletion without notice.</b> 51 * 52 * @since 1.2 53 * @author Atul M Dambalkar 54 * @author Robert Field 55 */ 56 public abstract class HtmlDocWriter extends HtmlWriter { 57 58 public static final String CONTENT_TYPE = "text/html"; 59 60 DocPath pathToRoot; 61 62 /** 63 * Constructor. Initializes the destination file name through the super 64 * class HtmlWriter. 65 * 66 * @param filename String file name. 67 */ 68 public HtmlDocWriter(Configuration configuration, DocPath filename) 69 throws IOException { 70 super(configuration, filename); 71 this.pathToRoot = filename.parent().invert(); 72 configuration.message.notice("doclet.Generating_0", 73 DocFile.createFileForOutput(configuration, filename).getPath()); 74 } 75 76 /** 77 * Accessor for configuration. 78 */ 79 public abstract Configuration configuration(); 80 81 public Content getHyperLink(DocPath link, String label) { 82 return getHyperLink(link, new StringContent(label), false, "", "", ""); 83 } 84 85 /** 86 * Get Html Hyper Link Content. 87 * 88 * @param where Position of the link in the file. Character '#' is not 89 * needed. 90 * @param label Tag for the link. 91 * @return a content tree for the hyper link 92 */ 93 public Content getHyperLink(String where, 94 Content label) { 95 return getHyperLink(getDocLink(where), label, "", ""); 96 } 97 98 /** 99 * Get Html Hyper Link Content. 100 * 101 * @param sectionName The section name to which the link will be created. 102 * @param label Tag for the link. 103 * @return a content tree for the hyper link 104 */ 105 public Content getHyperLink(SectionName sectionName, 106 Content label) { 107 return getHyperLink(getDocLink(sectionName), label, "", ""); 108 } 109 110 /** 111 * Get Html Hyper Link Content. 112 * 113 * @param sectionName The section name combined with where to which the link 114 * will be created. 115 * @param where The fragment combined with sectionName to which the link 116 * will be created. 117 * @param label Tag for the link. 118 * @return a content tree for the hyper link 119 */ 120 public Content getHyperLink(SectionName sectionName, String where, 121 Content label) { 122 return getHyperLink(getDocLink(sectionName, where), label, "", ""); 123 } 124 125 /** 126 * Get the link. 127 * 128 * @param where Position of the link in the file. 129 * @return a DocLink object for the hyper link 130 */ 131 public DocLink getDocLink(String where) { 132 return DocLink.fragment(getName(where)); 133 } 134 135 /** 136 * Get the link. 137 * 138 * @param sectionName The section name to which the link will be created. 139 * @return a DocLink object for the hyper link 140 */ 141 public DocLink getDocLink(SectionName sectionName) { 142 return DocLink.fragment(sectionName.getName()); 143 } 144 145 /** 146 * Get the link. 147 * 148 * @param sectionName The section name combined with where to which the link 149 * will be created. 150 * @param where The fragment combined with sectionName to which the link 151 * will be created. 152 * @return a DocLink object for the hyper link 153 */ 154 public DocLink getDocLink(SectionName sectionName, String where) { 155 return DocLink.fragment(sectionName.getName() + getName(where)); 156 } 157 158 /** 159 * Convert the name to a valid HTML name. 160 * 161 * @param name the name that needs to be converted to valid HTML name. 162 * @return a valid HTML name string. 163 */ 164 public String getName(String name) { 165 StringBuilder sb = new StringBuilder(); 166 char ch; 167 /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions 168 * that the name/id should begin with a letter followed by other valid characters. 169 * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction 170 * is that it should be at least one character long and should not contain spaces. 171 * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute. 172 * 173 * For HTML 4, we need to check for non-characters at the beginning of the name and 174 * substitute it accordingly, "_" and "$" can appear at the beginning of a member name. 175 * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z". 176 */ 177 for (int i = 0; i < name.length(); i++) { 178 ch = name.charAt(i); 179 switch (ch) { 180 case '(': 181 case ')': 182 case '<': 183 case '>': 184 case ',': 185 sb.append('-'); 186 break; 187 case ' ': 188 case '[': 189 break; 190 case ']': 191 sb.append(":A"); 192 break; 193 // Any appearance of $ needs to be substituted with ":D" and not with hyphen 194 // since a field name "P$$ and a method P(), both valid member names, can end 195 // up as "P--". A member name beginning with $ needs to be substituted with 196 // "Z:Z:D". 197 case '$': 198 if (i == 0) 199 sb.append("Z:Z"); 200 sb.append(":D"); 201 break; 202 // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor 203 // names can only begin with a letter. 204 case '_': 205 if (i == 0) 206 sb.append("Z:Z"); 207 sb.append(ch); 208 break; 209 default: 210 sb.append(ch); 211 } 212 } 213 return sb.toString(); 214 } 215 216 /** 217 * Get Html hyperlink. 218 * 219 * @param link path of the file. 220 * @param label Tag for the link. 221 * @return a content tree for the hyper link 222 */ 223 public Content getHyperLink(DocPath link, Content label) { 224 return getHyperLink(link, label, "", ""); 225 } 226 227 public Content getHyperLink(DocLink link, Content label) { 228 return getHyperLink(link, label, "", ""); 229 } 230 231 public Content getHyperLink(DocPath link, 232 Content label, boolean strong, 233 String stylename, String title, String target) { 234 return getHyperLink(new DocLink(link), label, strong, 235 stylename, title, target); 236 } 237 238 public Content getHyperLink(DocLink link, 239 Content label, boolean strong, 240 String stylename, String title, String target) { 241 Content body = label; 242 if (strong) { 243 body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body); 244 } 245 if (stylename != null && stylename.length() != 0) { 246 HtmlTree t = new HtmlTree(HtmlTag.FONT, body); 247 t.addAttr(HtmlAttr.CLASS, stylename); 248 body = t; 249 } 250 HtmlTree l = HtmlTree.A(link.toString(), body); 251 if (title != null && title.length() != 0) { 252 l.addAttr(HtmlAttr.TITLE, title); 253 } 254 if (target != null && target.length() != 0) { 255 l.addAttr(HtmlAttr.TARGET, target); 256 } 257 return l; 258 } 259 260 /** 261 * Get Html Hyper Link. 262 * 263 * @param link String name of the file. 264 * @param label Tag for the link. 265 * @param title String that describes the link's content for accessibility. 266 * @param target Target frame. 267 * @return a content tree for the hyper link. 268 */ 269 public Content getHyperLink(DocPath link, 270 Content label, String title, String target) { 271 return getHyperLink(new DocLink(link), label, title, target); 272 } 273 274 public Content getHyperLink(DocLink link, 275 Content label, String title, String target) { 276 HtmlTree anchor = HtmlTree.A(link.toString(), label); 277 if (title != null && title.length() != 0) { 278 anchor.addAttr(HtmlAttr.TITLE, title); 279 } 280 if (target != null && target.length() != 0) { 281 anchor.addAttr(HtmlAttr.TARGET, target); 282 } 283 return anchor; 284 } 285 286 /** 287 * Get the name of the package, this class is in. 288 * 289 * @param cd ClassDoc. 290 */ 291 public String getPkgName(ClassDoc cd) { 292 String pkgName = cd.containingPackage().name(); 293 if (pkgName.length() > 0) { 294 pkgName += "."; 295 return pkgName; 296 } 297 return ""; 298 } 299 300 public boolean getMemberDetailsListPrinted() { 301 return memberDetailsListPrinted; 302 } 303 304 /** 305 * Print the frames version of the Html file header. 306 * Called only when generating an HTML frames file. 307 * 308 * @param title Title of this HTML document 309 * @param configuration the configuration object 310 * @param body the body content tree to be added to the HTML document 311 */ 312 public void printFramesDocument(String title, ConfigurationImpl configuration, 313 HtmlTree body) throws IOException { 314 Content htmlDocType = configuration.isOutputHtml5() 315 ? DocType.HTML5 316 : DocType.TRANSITIONAL; 317 Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); 318 Content head = new HtmlTree(HtmlTag.HEAD); 319 head.addContent(getGeneratedBy(!configuration.notimestamp)); 320 Content windowTitle = HtmlTree.TITLE(new StringContent(title)); 321 head.addContent(windowTitle); 322 Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, 323 (configuration.charset.length() > 0) ? 324 configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET); 325 head.addContent(meta); 326 head.addContent(getStyleSheetProperties(configuration)); 327 head.addContent(getFramesJavaScript()); 328 Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), 329 head, body); 330 Content htmlDocument = new HtmlDocument(htmlDocType, 331 htmlComment, htmlTree); 332 write(htmlDocument); 333 } 334 335 /** 336 * Returns a link to the stylesheet file. 337 * 338 * @return an HtmlTree for the lINK tag which provides the stylesheet location 339 */ 340 public HtmlTree getStyleSheetProperties(ConfigurationImpl configuration) { 341 String stylesheetfile = configuration.stylesheetfile; 342 DocPath stylesheet; 343 if (stylesheetfile.isEmpty()) { 344 stylesheet = DocPaths.STYLESHEET; 345 } else { 346 DocFile file = DocFile.createFileForInput(configuration, stylesheetfile); 347 stylesheet = DocPath.create(file.getName()); 348 } 349 HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", 350 pathToRoot.resolve(stylesheet).getPath(), 351 "Style"); 352 return link; 353 } 354 355 protected Comment getGeneratedBy(boolean timestamp) { 356 String text = "Generated by javadoc"; // marker string, deliberately not localized 357 if (timestamp) { 358 Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); 359 Date today = calendar.getTime(); 360 text += " ("+ configuration.getDocletSpecificBuildDate() + ") on " + today; 361 } 362 return new Comment(text); 363 } 364 }