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