1 /* 2 * Copyright (c) 1998, 2020, 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 jdk.javadoc.internal.doclets.formats.html; 27 28 import java.net.MalformedURLException; 29 import java.net.URL; 30 import java.util.ArrayList; 31 import java.util.LinkedHashMap; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.Set; 35 import java.util.TreeSet; 36 37 import com.sun.tools.doclint.DocLint; 38 import jdk.javadoc.doclet.Doclet; 39 import jdk.javadoc.doclet.Reporter; 40 import jdk.javadoc.internal.doclets.toolkit.BaseOptions; 41 import jdk.javadoc.internal.doclets.toolkit.Resources; 42 import jdk.javadoc.internal.doclets.toolkit.util.DocFile; 43 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 44 45 import static javax.tools.Diagnostic.Kind.ERROR; 46 import static javax.tools.Diagnostic.Kind.WARNING; 47 48 /** 49 * Storage for all options supported by the 50 * {@link jdk.javadoc.doclet.StandardDoclet standard doclet}, 51 * including the format-independent options handled 52 * by {@link BaseOptions}. 53 * 54 */ 55 public class HtmlOptions extends BaseOptions { 56 //<editor-fold desc="Option values"> 57 /** 58 * Argument for command-line option {@code --add-stylesheet}. 59 */ 60 public List<String> additionalStylesheets = new ArrayList<>(); 61 62 /** 63 * Argument for command-line option {@code -bottom}. 64 */ 65 public String bottom = ""; 66 67 /** 68 * Argument for command-line option {@code -charset}. 69 * The META charset tag used for cross-platform viewing. 70 */ 71 public String charset = null; 72 73 /** 74 * Argument for command-line option {@code -use}. 75 * True if command-line option "-use" is used. Default value is false. 76 */ 77 public boolean classUse = false; 78 79 /** 80 * Argument for command-line option {@code -noindex}. 81 * False if command-line option "-noindex" is used. Default value is true. 82 */ 83 public boolean createIndex = true; 84 85 /** 86 * Argument for command-line option {@code -overview}. 87 * This is true if option "-overview" is used or option "-overview" is not 88 * used and number of packages is more than one. 89 */ 90 public boolean createOverview = false; 91 92 /** 93 * Argument for command-line option {@code -notree}. 94 * False if command-line option "-notree" is used. Default value is true. 95 */ 96 public boolean createTree = true; 97 98 /** 99 * Arguments for command-line option {@code -Xdoclint} and friends. 100 * Collected set of doclint options. 101 */ 102 public Map<Doclet.Option, String> doclintOpts = new LinkedHashMap<>(); 103 104 /** 105 * Argument for command-line option {@code -Xdocrootparent}. 106 */ 107 public String docrootParent = ""; 108 109 /** 110 * Argument for command-line option {@code -doctitle}. 111 */ 112 public String docTitle = ""; 113 114 115 /** 116 * Argument for command-line option {@code -footer}. 117 */ 118 public String footer = ""; 119 120 /** 121 * Argument for command-line option {@code -header}. 122 */ 123 public String header = ""; 124 125 /** 126 * Argument for command-line option {@code -helpfile}. 127 */ 128 public String helpFile = ""; 129 130 /** 131 * Argument for command-line option {@code -nodeprecated}. 132 * True if command-line option "-nodeprecated" is used. Default value is 133 * false. 134 */ 135 public boolean noDeprecatedList = false; 136 137 /** 138 * Argument for command-line option {@code -nohelp}. 139 * True if command-line option "-nohelp" is used. Default value is false. 140 */ 141 public boolean noHelp = false; 142 143 /** 144 * Argument for command-line option {@code -nonavbar}. 145 * True if command-line option "-nonavbar" is used. Default value is false. 146 */ 147 public boolean noNavbar = false; 148 149 /** 150 * Argument for command-line option {@code -nooverview}. 151 * True if command-line option "-nooverview" is used. Default value is 152 * false 153 */ 154 boolean noOverview = false; 155 156 /** 157 * Argument for command-line option {@code -overview}. 158 * The overview path specified with "-overview" flag. 159 */ 160 public String overviewPath = null; 161 162 /** 163 * Argument for command-line option {@code -packagesheader}. 164 */ 165 public String packagesHeader = ""; 166 167 /** 168 * Argument for command-line option {@code -splitindex}. 169 * True if command-line option "-splitindex" is used. Default value is 170 * false. 171 */ 172 public boolean splitIndex = false; 173 174 /** 175 * Argument for command-line option {@code -stylesheetfile}. 176 */ 177 public String stylesheetFile = ""; 178 179 /** 180 * Argument for command-line option {@code -top}. 181 */ 182 public String top = ""; 183 184 /** 185 * Argument for command-line option {@code -windowtitle}. 186 */ 187 public String windowTitle = ""; 188 //</editor-fold> 189 190 private HtmlConfiguration config; 191 192 HtmlOptions(HtmlConfiguration config) { 193 super(config); 194 this.config = config; 195 } 196 197 @Override 198 public Set<? extends Option> getSupportedOptions() { 199 Resources resources = config.getResources(); 200 Reporter reporter = config.getReporter(); 201 202 List<Option> options = List.of( 203 new Option(resources, "--add-stylesheet", 1) { 204 @Override 205 public boolean process(String opt, List<String> args) { 206 additionalStylesheets.add(args.get(0)); 207 return true; 208 } 209 }, 210 211 new Option(resources, "-bottom", 1) { 212 @Override 213 public boolean process(String opt, List<String> args) { 214 bottom = args.get(0); 215 return true; 216 } 217 }, 218 219 new Option(resources, "-charset", 1) { 220 @Override 221 public boolean process(String opt, List<String> args) { 222 charset = args.get(0); 223 return true; 224 } 225 }, 226 227 new Option(resources, "-doctitle", 1) { 228 @Override 229 public boolean process(String opt, List<String> args) { 230 docTitle = args.get(0); 231 return true; 232 } 233 }, 234 235 new Option(resources, "-footer", 1) { 236 @Override 237 public boolean process(String opt, List<String> args) { 238 footer = args.get(0); 239 return true; 240 } 241 }, 242 243 new Option(resources, "-header", 1) { 244 @Override 245 public boolean process(String opt, List<String> args) { 246 header = args.get(0); 247 return true; 248 } 249 }, 250 251 new Option(resources, "-helpfile", 1) { 252 @Override 253 public boolean process(String opt, List<String> args) { 254 if (noHelp) { 255 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 256 "-helpfile", "-nohelp")); 257 return false; 258 } 259 if (!helpFile.isEmpty()) { 260 reporter.print(ERROR, resources.getText("doclet.Option_reuse", 261 "-helpfile")); 262 return false; 263 } 264 helpFile = args.get(0); 265 return true; 266 } 267 }, 268 269 new Option(resources, "-html5") { 270 @Override 271 public boolean process(String opt, List<String> args) { 272 return true; 273 } 274 }, 275 276 new Option(resources, "-nohelp") { 277 @Override 278 public boolean process(String opt, List<String> args) { 279 noHelp = true; 280 if (!helpFile.isEmpty()) { 281 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 282 "-nohelp", "-helpfile")); 283 return false; 284 } 285 return true; 286 } 287 }, 288 289 new Option(resources, "-nodeprecatedlist") { 290 @Override 291 public boolean process(String opt, List<String> args) { 292 noDeprecatedList = true; 293 return true; 294 } 295 }, 296 297 new Option(resources, "-noindex") { 298 @Override 299 public boolean process(String opt, List<String> args) { 300 createIndex = false; 301 if (splitIndex) { 302 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 303 "-noindex", "-splitindex")); 304 return false; 305 } 306 return true; 307 } 308 }, 309 310 new Option(resources, "-nonavbar") { 311 @Override 312 public boolean process(String opt, List<String> args) { 313 noNavbar = true; 314 return true; 315 } 316 }, 317 318 new Hidden(resources, "-nooverview") { 319 @Override 320 public boolean process(String opt, List<String> args) { 321 noOverview = true; 322 if (overviewPath != null) { 323 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 324 "-nooverview", "-overview")); 325 return false; 326 } 327 return true; 328 } 329 }, 330 331 new Option(resources, "-notree") { 332 @Override 333 public boolean process(String opt, List<String> args) { 334 createTree = false; 335 return true; 336 } 337 }, 338 339 new Option(resources, "-overview", 1) { 340 @Override 341 public boolean process(String opt, List<String> args) { 342 overviewPath = args.get(0); 343 if (noOverview) { 344 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 345 "-overview", "-nooverview")); 346 return false; 347 } 348 return true; 349 } 350 }, 351 352 new Hidden(resources, "-packagesheader", 1) { 353 @Override 354 public boolean process(String opt, List<String> args) { 355 packagesHeader = args.get(0); 356 return true; 357 } 358 }, 359 360 new Option(resources, "-splitindex") { 361 @Override 362 public boolean process(String opt, List<String> args) { 363 splitIndex = true; 364 if (!createIndex) { 365 reporter.print(ERROR, resources.getText("doclet.Option_conflict", 366 "-splitindex", "-noindex")); 367 return false; 368 } 369 return true; 370 } 371 }, 372 373 new Option(resources, "--main-stylesheet -stylesheetfile", 1) { 374 @Override 375 public boolean process(String opt, List<String> args) { 376 stylesheetFile = args.get(0); 377 return true; 378 } 379 }, 380 381 new Option(resources, "-top", 1) { 382 @Override 383 public boolean process(String opt, List<String> args) { 384 top = args.get(0); 385 return true; 386 } 387 }, 388 389 new Option(resources, "-use") { 390 @Override 391 public boolean process(String opt, List<String> args) { 392 classUse = true; 393 return true; 394 } 395 }, 396 397 new Option(resources, "-windowtitle", 1) { 398 @Override 399 public boolean process(String opt, List<String> args) { 400 windowTitle = args.get(0).replaceAll("<.*?>", ""); 401 return true; 402 } 403 }, 404 405 new XOption(resources, "-Xdoclint") { 406 @Override 407 public boolean process(String opt, List<String> args) { 408 doclintOpts.put(this, DocLint.XMSGS_OPTION); 409 return true; 410 } 411 }, 412 413 new XOption(resources, "-Xdocrootparent", 1) { 414 @Override 415 public boolean process(String opt, List<String> args) { 416 docrootParent = args.get(0); 417 try { 418 new URL(docrootParent); 419 } catch (MalformedURLException e) { 420 reporter.print(ERROR, resources.getText("doclet.MalformedURL", docrootParent)); 421 return false; 422 } 423 return true; 424 } 425 }, 426 427 new XOption(resources, "doclet.usage.xdoclint-extended", "-Xdoclint:", 0) { 428 @Override 429 public boolean process(String opt, List<String> args) { 430 String dopt = opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX); 431 doclintOpts.put(this, dopt); 432 if (dopt.contains("/")) { 433 reporter.print(ERROR, resources.getText("doclet.Option_doclint_no_qualifiers")); 434 return false; 435 } 436 if (!DocLint.isValidOption(dopt)) { 437 reporter.print(ERROR, resources.getText("doclet.Option_doclint_invalid_arg")); 438 return false; 439 } 440 return true; 441 } 442 }, 443 444 new XOption(resources, "doclet.usage.xdoclint-package", "-Xdoclint/package:", 0) { 445 @Override 446 public boolean process(String opt, List<String> args) { 447 String dopt = opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE); 448 doclintOpts.put(this, dopt); 449 if (!DocLint.isValidOption(dopt)) { 450 reporter.print(ERROR, resources.getText("doclet.Option_doclint_package_invalid_arg")); 451 return false; 452 } 453 return true; 454 } 455 }, 456 457 new XOption(resources, "--no-frames") { 458 @Override 459 public boolean process(String opt, List<String> args) { 460 reporter.print(WARNING, resources.getText("doclet.NoFrames_specified")); 461 return true; 462 } 463 } 464 ); 465 Set<BaseOptions.Option> allOptions = new TreeSet<>(); 466 allOptions.addAll(options); 467 allOptions.addAll(super.getSupportedOptions()); 468 return allOptions; 469 } 470 471 protected boolean validateOptions() { 472 // check shared options 473 if (!generalValidOptions()) { 474 return false; 475 } 476 477 Resources resources = config.getResources(); 478 Reporter reporter = config.getReporter(); 479 480 // check if helpfile exists 481 if (!helpFile.isEmpty()) { 482 DocFile help = DocFile.createFileForInput(config, helpFile); 483 if (!help.exists()) { 484 reporter.print(ERROR, resources.getText("doclet.File_not_found", helpFile)); 485 return false; 486 } 487 } 488 // check if stylesheetFile exists 489 if (!stylesheetFile.isEmpty()) { 490 DocFile stylesheet = DocFile.createFileForInput(config, stylesheetFile); 491 if (!stylesheet.exists()) { 492 reporter.print(ERROR, resources.getText("doclet.File_not_found", stylesheetFile)); 493 return false; 494 } 495 } 496 // check if additional stylesheets exists 497 for (String ssheet : additionalStylesheets) { 498 DocFile ssfile = DocFile.createFileForInput(config, ssheet); 499 if (!ssfile.exists()) { 500 reporter.print(ERROR, resources.getText("doclet.File_not_found", ssheet)); 501 return false; 502 } 503 } 504 505 // In a more object-oriented world, this would be done by methods on the Option objects. 506 // Note that -windowtitle silently removes any and all HTML elements, and so does not need 507 // to be handled here. 508 Utils utils = config.utils; 509 utils.checkJavaScriptInOption("-header", header); 510 utils.checkJavaScriptInOption("-footer", footer); 511 utils.checkJavaScriptInOption("-top", top); 512 utils.checkJavaScriptInOption("-bottom", bottom); 513 utils.checkJavaScriptInOption("-doctitle", docTitle); 514 utils.checkJavaScriptInOption("-packagesheader", packagesHeader); 515 516 return true; 517 } 518 519 }