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